2016-12-06 5 views
5

Я разрабатываю приложение для Android, в котором я должен запрашивать разрешения во время выполнения. Мне интересно, как наилучшим образом реализовать это с помощью архитектуры Model-View-Presenter.Каков наилучший способ проверки разрешений во время выполнения с использованием архитектуры MVP?

Моя первоначальная мысль заключалась в том, что ведущий вызывал компонент, отвечающий за разрешения (например, PermissionHandler), и соответственно обновляйте представление.

Проблема в том, что код для проверки разрешений тесно связан с классом Activity. Вот некоторые из методов, участвующих, которые требуют активности или контекста:

  • ContextCompat.checkSelfPermission()
  • ActivityCompat.shouldShowRequestPermissionRationale()
  • ActivityCompat.requestPermissions()
  • onRequestPermissionsResult() (обратный вызов)

Это означает, что я должен был бы пройти объект активности для ведущего, которого мне не очень понравилось, потому что я слышал, что держать презентатора бесплатно от кода Android хорошо для testin г.

В связи с этим я тогда подумал о том, как обращаться с разрешениями на уровне представления (в действии), но тогда я предполагаю, что это повредит цели оставлять представление ответственным только за обновления пользовательского интерфейса без бизнес-логики.

Я не уверен, что было бы лучшим подходом к решению проблемы с тем, чтобы код был как можно более разборчивым и поддерживаемым. Есть идеи?

ответ

7

Что бы я сделал это:

мнение будет осуществлять:

public Activity getViewActivity(); 

Ведущий будет осуществлять:

public void requestPermissions(); 
public void onPermissionsResult(); 

Внутри requestPermissions, ведущий будет делать: getViewActivity().checkSelfPermission; getViewActivity.requestPermissions(); etc.

Вид вызовет внутри onRequestPermissionsResult callback to presenter.onPermissionsResult();

При этом вся логика будет реализована внутри презентатора.

На мой взгляд, ваш презентатор развязан: он не будет зависеть от какой-либо реализации представления (он будет зависеть только от интерфейса вида).

«Я слышал, что держать вашего презентатора бесплатно от кода Android хорошо для тестирования». Я не понимаю эту часть. Если код хорош, его можно протестировать без каких-либо проблем.

+0

Будет ли этот подход безопасным? Разве это не приведет к утечке памяти? – fobo66

1

Если вы все еще хотите, чтобы иметь возможность издеваться над правами доступа/запросами, вы все равно создаете что-то вроде 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)

public class PermissionsHandlerMocked implements PermissionsHandler { 
    @Override 
    public boolean checkHasPermission(AppCompatActivity activity, String permission) { 
     return false; 
    } 

    @Override 
    public void requestPermission(AppCompatActivity activity, String[] permissions, int requestCode){ 
     int[] grantResults = new int[permissions.length]; 
     for (int i = 0; i < permissions.length; i++) { 
      grantResults[i] = PackageManager.PERMISSION_GRANTED 
     } 
     activity.onRequestPermissionResult(requestCode, permissions, grantResults); 
    } 
} 

Затем в вашей деятельности:

PermissionsHandler permissionsHandler; 

@Override 
protected void onCreate(@Nullable Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    permissionsHandler = Injection.providePermissionsHandler(); 
    //or however you choose to inject your production vs mocked handler. 
} 

//method from your view interface, to be called by your presenter 
@Override 
void requestLocationPermission() { 
    permissionsHandler.requestPermision((AppCompatActivity) this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE_LOCATION}; 
} 

fobo66, вы всегда можете сделать вид реализовать гораздо более общие методы, такие как checkLocationPermissionGranted() и requestLocationPermission(). Тогда ваша реализация представления может ссылаться на активность по мере необходимости, и вашему ведущему никогда не придется прикасаться к ссылке на действие.