在 MVP 中使用 Kotlin 高阶函数

Use Kotlin higher order functions in MVP

通常使用 Java,我们创建一个 *Contract 接口来处理 ViewPresenter 之间的交互,喜欢:

MainActivity
作为View

public class MainActivity extends Activity implements MainContract {

@Override
public void onCreate(Bundle b) {
   presenter.requestData();
}

@Override
public void showData(String data) {
   // Handle data ...
}

MainPresenter
作为 Presenter

public class MainPresenter {

   public void requestData() {
      contract.showData("data");
   }
}

主合约
作为interface

public interface MainContract {
   void showData(String data);
}

既然 Kotlin 具有 "Higher order function" 的特性,应该 我们是否应该简单地传递函数来处理视图和呈现器之间的交互?它可以是这样的:

查看:

presenter.requestData { data ->
   // Handle data
}

主持人:

fun requestData(handler: (String) -> Unit) {
   handler("data")
}

我不是在问可能性,我是在问这是否是最佳实践。

这个问题的答案更多是相关的体系结构决策,而不是技术限制。您可以在 Java 中(甚至在 Java7 中)使用匿名实例实现同样的事情(当然它会有更多的样板文件并且更难阅读)。

MVP 中关于拥有视图实现的合同的想法是每个演示者都知道如何获取、操作和呈现所述合同。潜在的视图可以实现多个契约并有多个演示者。此外,每个演示者实例仅适用于合同的一种实现,但您可以有两个实例服务于两种不同的实现。

如果不是每个视图都符合每个演示者的合同,而是演示者的每次调用都采用 lambda,那么您迟早会遇到问题。

例如,想象一个呈现器异步获取数据并将其缓存在内存中:

  1. 视图调用呈现器方法fetchData()
  2. 提交者调用合约的showLoading()方法。
  3. (一段时间过去了)
  4. 演示者调用合约的 hideLoading()showData(data) 方法。
  5. 用户再次互动并触发fetchData()
  6. 演示者使用缓存数据调用showData()

在这种情况下,如果我们使用 lambda 而不是契约,我们将需要在同一方法中请求两个不同的 lambda:一个用于缓存,一个用于缓存。 我们也正在将视图实现耦合到呈现器,将来呈现器接口的另一个实现可能不需要这两个 lambda,因为逻辑已经改变。

重要的是要记住,在理想情况下,在 MVP 中,视图和呈现器都通过接口相互通信,在这种情况下,呈现器接口不应受到实现细节的影响,而应仅公开它们能够执行的操作。