Android 什么';使用MVP架构在运行时检查权限的最佳方法是什么?
我正在开发一个android应用程序,在其中我必须在运行时请求权限。我想知道使用Model View Presenter体系结构实现该功能的最佳方法 我最初的想法是让演示者调用负责权限的组件(比如Android 什么';使用MVP架构在运行时检查权限的最佳方法是什么?,android,android-permissions,mvp,Android,Android Permissions,Mvp,我正在开发一个android应用程序,在其中我必须在运行时请求权限。我想知道使用Model View Presenter体系结构实现该功能的最佳方法 我最初的想法是让演示者调用负责权限的组件(比如PermissionHandler),并相应地更新视图 问题在于检查权限的代码与活动类紧密耦合。以下是一些需要活动或上下文的方法: ContextCompat.checkSelfPermission() ActivityCompat.shouldShowRequestPermissionRegulat
PermissionHandler
),并相应地更新视图
问题在于检查权限的代码与活动类紧密耦合。以下是一些需要活动或上下文的方法:
ContextCompat.checkSelfPermission()
ActivityCompat.shouldShowRequestPermissionRegulation()
ActivityCompat.requestPermissions()
(回调)onRequestPermissionsResult()
public Activity getViewActivity();
public void requestPermissions();
public void onPermissionsResult();
演示者将实现:
public Activity getViewActivity();
public void requestPermissions();
public void onPermissionsResult();
在requestPermissions
中,演示者将执行以下操作:getViewActivity();getViewActivity.requestPermissions();等等。
该视图将在onRequestPermissionsResult
回调中调用presenter.onPermissionsResult()代码>
所有的逻辑都将在演示者内部实现
在我看来,演示者是解耦的:它不依赖于任何视图实现(它只依赖于视图接口)
“我听说让演示者远离Android代码有利于测试。”我不理解这一部分。如果代码良好,则可以毫无问题地对其进行测试。如果仍然希望能够模拟权限访问/请求,则仍然可以创建类似于PermissionHandler的内容,但只能在视图类中引用它。比如说-
接口:
public interface PermissionsHandler {
boolean checkHasPermission(AppCompatActivity activity, String permission);
void requestPermission(AppCompatActivity activity, String[] permissions, int requestCode);
}
生产实施:
public class PermissionsHandlerAndroid implements PermissionsHandler {
@Override
public boolean checkHasPermission(AppCompatActivity activity, String permission) {
return ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED;
}
@Override
public void requestPermission(AppCompatActivity activity, String[] permissions, int requestCode){
ActivityCompat.requestPermissions(activity, permissions, requestCode);
}
}
模拟类(例如,测试并确保您的活动正确地处理了onRequestPermissionsResult
)
,则始终可以使视图实现更通用的方法,如
checkLocationPermissionGrassed()
和requestLocationPermission()
。然后,您的视图实现可以根据需要引用活动,并且您的演示者永远不必触摸活动引用 权限请求和状态是视图(片段或活动)的责任,因为依赖于用户的操作来发出请求或授予权限。我使用MVP管理权限,如下所示(阅读外部存储示例):
我的合同
interface View {
...
void requestReadPermission();
boolean areReadPermissionGranted();
void showPermissionError();
void hidePermissionError();
...
}
interface Presenter {
...
void setReadPermissions(boolean grantedPermissions);
...
}
interface Model {
...
}
我的观点是实现。(在本例中为片段,但它可以是活动或其他内容,演示者只希望得到响应)
以及演示者实现
public class MyPresenter implements Contract.Presenter {
...
Contract.View view;
public void doSomethingThatRequiresPermissions() {
...
if ( !view.areReadPermissionGranted() ) {
view.requestReadPermission();
view.showPermissionError();
} else {
view.hidePermissionError();
doSomethingWithPermissionsGranted();
}
...
}
@Override
public void setReadPermissions(boolean grantedPermissions) {
if( grantedPermissions ){
view.hidePermissionError();
doSomethingThatRequiresPermissions();
} else {
view.showPermissionError();
}
}
public void doSomethingWithPermissionsGranted(){
...
}
然后你可以像这样做单元测试
Contract.View mockedView;
@Test
public void requestAlbumListWithoutPermissions() {
when(mockedView.areReadPermissionGranted()).thenReturn(false);
presenter.doSomethingWithPermissionsGranted();
verify(mockedView).showPermissionError();
verify(mockedView).requestReadPermission();
}
这种方法安全吗?它不应该产生内存泄漏吗?这种方法与MVP体系结构如何配合?演示者的全部要点是让您的业务逻辑代码基于纯java或kotlin,并且独立于任何android框架组件,以便可以轻松地进行单元测试。这不应该是公认的答案。这就是这个解决方案的作用。演示者依赖于视图与自身之间的契约,与任何其他框架都没有依赖关系。你们知道,模仿它来做测试是很简单的。@mromer实际上是在编写代码。您将看到演示者具有活动的导入语句。
Contract.View mockedView;
@Test
public void requestAlbumListWithoutPermissions() {
when(mockedView.areReadPermissionGranted()).thenReturn(false);
presenter.doSomethingWithPermissionsGranted();
verify(mockedView).showPermissionError();
verify(mockedView).requestReadPermission();
}