Android架构:RxJava+MVVM

MVP的一些小问题

说到Android应用开发的架构,大多数人可能都会说出MVP。

的确,MVP架构的出现为我们的Activity和Fragment的减肥瘦身做出的很大的贡献。但是基于一些原因,我和小伙伴们决定无情的将他抛弃,寻求更好的方案。

起因是这样的,在一次迭代中,我们决定将DI(dagger2)引入到项目中,而且我们顺理成章的认为,MVP也可以通过注入方式初始化,想象的代码能变成这样:

class MainActivity implement MainView{
  @Inject MainPresenter presenter;
  ...
}

class MainPresenter {
  @Inject MainView view;
  @Inject MainModel model;
  ...
}

但在后来接入的过程中,我们发现这个方案没有办法直接走通。因为在MainPresenter中注入view时,dagger并不知道view的实例从何而来,因此我们需要借助一个Module来把view的实例provide出来:

@Module
class MainModule {
  MainActivity activity;
  MainMoudle(MainActivity activity) { this.activity = activity; }
  @Provide MainView mainView(){ return activity; }
}

这意味着,每个Activity都需要建立一个对应的Module,这样每次初始化Component的成本,和我们用传统方式在Presenter里绑定View的成本没有什么区别。

传统方式绑定:

class MainActivity implement MainView {
  MainPresenter presenter;
  void onCreate(){
    presenter = new MainPresenter(this);
  }
}

的确,对于DI的使用来说,这种绑定方式理所应当。究其原因,是因为在MVP中,View和Presenter互相引用了。

除此之外,相互引用还会造成很多问题。比如异步操作可能会造成View无法回收;比如Presenter大多时候无法重用。。

结合J2EE成熟的后端架构来看。MVP做到了分离界面和业务代码,但是模块化,分层,可复用等等的功能都比较难使用。所以与其说是一种“架构”,不如称之为一种“代码优化方式”更为恰当。

MVVM怎么做

假设需求是读取手机联系人并显示,MVP的做法是:

class Presenter {
  void loadContacts(){
    new Thread(()->{
      // .... 加载联系人
      view.showContacts(contactsList);
    }).start();
  }
}

interface View {
  void showContacts(List contactsList);
}

MVVM也类似,但是他不直接把列表传给view,而是传给一个可订阅对象,在RxJava里我们使用Subject:

class ViewModel {
  Subject,List> loadContactsObs = PublishSubject.create();
  void loadContacts() {
    new Thread(()->{
      // .... 加载联系人
      loadContactsObs.onNext(contactsList); // 让subject接收联系人列表
    }).start();
  }
}

class Activity {
  ViewModel viewModel;
  void onCreate(){
    viewMode.loadContactsObs.subscribe(list ->
        this.showContacts(list));
    viewMode.loadContacts();
  }
}

这样一来,Actvity持有ViewModel,ViewModel进一步持有处理业务关系的模块。每个模块之间不会有互相的引用。这样带来的好处有:

首先,我们的注入代码变成了类似:

class MainActivity {
  @Inject MainViewModel viewModel;
  ...
}

class MainViewModel {
  @Inject MainModel model;
  ...
}

其次,ViewModel真正实现了可重用。不像实现Presenter必须实现对应的View,使用ViewModel我们可以灵活选择订阅/不订阅相应的返回事件。

还有,由于订阅的是Rx的Subject,我们可以使用Rx带的强大的api直接进行逻辑优化~

大概的介绍就是这样,实际开发过程中也出现了不少的问题和可优化的地方,例如MVP面向接口编程的思想,同样可以应用到MVVM中;例如MVVM结合DI的进一步优化等等,需要之后好好整理一下。

你可能感兴趣的:(Android架构:RxJava+MVVM)