2016-12-06 17 views
5

Pracuję nad aplikacją dla systemu Android, w której muszę prosić o uprawnienia w czasie wykonywania. Zastanawiam się nad najlepszym sposobem wdrożenia tego przy użyciu architektury Model-View-Presenter.Jaki jest najlepszy sposób sprawdzania uprawnień w środowisku wykonawczym przy użyciu architektury MVP?

Moja początkowa myśl polegała na tym, aby prezenter zadzwonił do komponentu odpowiedzialnego za uprawnienia (powiedzmy PermissionHandler) i odpowiednio zaktualizuj widok.

Problem polega na tym, że kod sprawdzający uprawnienia jest ściśle powiązany z klasą aktywności. Oto niektóre z metod związane, które wymagają aktywności lub okoliczności:

  • ContextCompat.checkSelfPermission()
  • ActivityCompat.shouldShowRequestPermissionRationale()
  • ActivityCompat.requestPermissions()
  • onRequestPermissionsResult() (zwrotna)

Oznacza to, że trzeba przepuścić obiekt aktywności dla prezentera, który mi się nie podobał, bo słyszałem, że trzymanie prezentera wolnego od kodu Androida jest dobre dla testowania sol.

Z tego powodu, pomyślałem o obsłudze uprawnień na poziomie widoku (w działaniu), ale wtedy myślę, że zaszkodziłoby to celowi pozostawienia widoku odpowiedzialnego tylko za aktualizacje interfejsu, bez logiki biznesowej.

Nie jestem pewien, jaki byłby najlepszy sposób rozwiązania tego problemu, utrzymując kod jako odłączony i możliwy do utrzymania. Jakieś pomysły?

Odpowiedz

7

Co chciałbym zrobić, to:

Widok wdroży:

public Activity getViewActivity(); 

Prezenter będzie realizować:

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

Wewnątrz requestPermissions, prezenter zrobi: getViewActivity().checkSelfPermission; getViewActivity.requestPermissions(); etc.

Widok zostanie wywołany wewnątrz onRequestPermissionsResult oddzwanianie do presenter.onPermissionsResult();

Dzięki temu cała logika zostanie zaimplementowana wewnątrz prezentera.

Moim zdaniem, twój prezenter jest odłączony: nie będzie zależał od jakiejkolwiek implementacji widoku (będzie zależał tylko od interfejsu widoku).

"Słyszałem, że trzymanie prezentera wolnego od kodu Androida jest dobre do testowania." Nie rozumiem tej części. Jeśli kod jest dobry, można go przetestować bez problemu.

+0

Czy to podejście będzie bezpieczne? Czy nie powinien generować wycieku pamięci? – fobo66

1

Jeśli nadal chcesz mieć możliwość sfałszowania dostępu/żądań uprawnień, nadal możesz utworzyć coś takiego, jak PermissionHandler, ale tylko odwoływać się do niego wewnątrz klasy widoku.Na przykład -

Interfejs:

public interface PermissionsHandler { 
    boolean checkHasPermission(AppCompatActivity activity, String permission); 
    void requestPermission(AppCompatActivity activity, String[] permissions, int requestCode); 
} 

realizacja Produkcja:

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); 
    } 
} 

szydzili klasy (na przykład, aby przetestować i upewnić się, że aktywność poprawnie obsługuje 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); 
    } 
} 

Następnie w swojej działalności:

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, zawsze można zrobić widok wdrożenie metod znacznie bardziej ogólnych jak checkLocationPermissionGranted() i requestLocationPermission(). Następnie implementacja widoku może odwoływać się do działania w razie potrzeby, a prezenter nigdy nie musi dotykać odwołania do działania.

Powiązane problemy