Android-cleanarchitecture: Limiting use of Android specific classes in presenters

Created on 6 Nov 2016  路  2Comments  路  Source: android10/Android-CleanArchitecture

What do you think about an idea to remove access to Context object in presenters to make it platform-independent? It could be achieved by making, for example, Navigator not Singleton but with PerView scope and add Host activity as a construtor parameter? Is it worth the sweat?

Most helpful comment

@romansbobans I think, the presenter should't have any platform dependencies, only java and then you can test presenter using only JUnit.

For navigation good solution is to use Router pattern. Like a View interface you have Router interface which define navigation methods.
For example:

public interface IRouter {
}
public interface CategoryRouter extends IRouter {

  void openEditCategoryScreen(CategoryViewModel category);
}
public interface Router<R extends IRouter> {

  void detachRouter();

  void attachRouter(R router);

  boolean hasRouter();

  R getRouter();
}



md5-08df37e04c15aa064ca4b6c00ea72264



public abstract class BaseRouterPresenter<V extends MvpView, R extends IRouter>
    extends BasePresenter<V> implements Router<R> {

  private PresenterRouterDelegate<R> routerDelegate;

  public BaseRouterPresenter() {
    super();
    routerDelegate = new PresenterRouterDelegate<>();
  }

  @Override public void detachRouter() {
    routerDelegate.detachRouter();
  }

  @Override public void attachRouter(R router) {
    routerDelegate.attachRouter(router);
  }

  @Override public boolean hasRouter() {
    return routerDelegate.hasRouter();
  }

  @Override public R getRouter() {
    return routerDelegate.getRouter();
  }
}
````



md5-9036f6ae632dfbd33fc5aab77a899bb6




In you presenter 



md5-bffcfb9187323f64442930671705847a



public class CategoriesActivity extends Activity implements CategoryRouter {

@Inject protected Navigator navigator;

@Override public void openEditCategoryScreen(CategoryViewModel category) {
navigator.navigateToAddCategoryScreen(this, category);
}

```
Why this pattern is good?
1) You code become more readable. Imagine the situation when you open Activity or Fragment and you want to understand navigation flow on this screen. For this you need to find code responsible for navigation. It will take some time, especially when you new on project.
With router you just need to open interface and see where you can go from this screen.

2) I think it's bad way to use Navigator in presenter, because Navigator containe all navigation logic.
And it's allow us to invoke any navigation method in presenter. It's bad, we need borders and router provide them.

3) Easy to test, just mock interface.

Sorry for my bad english :))

All 2 comments

@romansbobans I think, the presenter should't have any platform dependencies, only java and then you can test presenter using only JUnit.

For navigation good solution is to use Router pattern. Like a View interface you have Router interface which define navigation methods.
For example:

public interface IRouter {
}
public interface CategoryRouter extends IRouter {

  void openEditCategoryScreen(CategoryViewModel category);
}
public interface Router<R extends IRouter> {

  void detachRouter();

  void attachRouter(R router);

  boolean hasRouter();

  R getRouter();
}



md5-08df37e04c15aa064ca4b6c00ea72264



public abstract class BaseRouterPresenter<V extends MvpView, R extends IRouter>
    extends BasePresenter<V> implements Router<R> {

  private PresenterRouterDelegate<R> routerDelegate;

  public BaseRouterPresenter() {
    super();
    routerDelegate = new PresenterRouterDelegate<>();
  }

  @Override public void detachRouter() {
    routerDelegate.detachRouter();
  }

  @Override public void attachRouter(R router) {
    routerDelegate.attachRouter(router);
  }

  @Override public boolean hasRouter() {
    return routerDelegate.hasRouter();
  }

  @Override public R getRouter() {
    return routerDelegate.getRouter();
  }
}
````



md5-9036f6ae632dfbd33fc5aab77a899bb6




In you presenter 



md5-bffcfb9187323f64442930671705847a



public class CategoriesActivity extends Activity implements CategoryRouter {

@Inject protected Navigator navigator;

@Override public void openEditCategoryScreen(CategoryViewModel category) {
navigator.navigateToAddCategoryScreen(this, category);
}

```
Why this pattern is good?
1) You code become more readable. Imagine the situation when you open Activity or Fragment and you want to understand navigation flow on this screen. For this you need to find code responsible for navigation. It will take some time, especially when you new on project.
With router you just need to open interface and see where you can go from this screen.

2) I think it's bad way to use Navigator in presenter, because Navigator containe all navigation logic.
And it's allow us to invoke any navigation method in presenter. It's bad, we need borders and router provide them.

3) Easy to test, just mock interface.

Sorry for my bad english :))

i totally agree! for that reason my presenters, models and view interfaces are in a separated java module.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Cook1 picture Cook1  路  4Comments

misrakli picture misrakli  路  5Comments

Joy-Whale picture Joy-Whale  路  5Comments

mr746866 picture mr746866  路  3Comments

Neoklosch picture Neoklosch  路  6Comments