在 MVP 中使用 Kotlin 高阶函数
Use Kotlin higher order functions in MVP
通常使用 Java,我们创建一个 *Contract
接口来处理 View 和 Presenter 之间的交互,喜欢:
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,那么您迟早会遇到问题。
例如,想象一个呈现器异步获取数据并将其缓存在内存中:
- 视图调用呈现器方法
fetchData()
。
- 提交者调用合约的
showLoading()
方法。
- (一段时间过去了)
- 演示者调用合约的
hideLoading()
和 showData(data)
方法。
- 用户再次互动并触发
fetchData()
- 演示者使用缓存数据调用
showData()
在这种情况下,如果我们使用 lambda 而不是契约,我们将需要在同一方法中请求两个不同的 lambda:一个用于缓存,一个用于缓存。
我们也正在将视图实现耦合到呈现器,将来呈现器接口的另一个实现可能不需要这两个 lambda,因为逻辑已经改变。
重要的是要记住,在理想情况下,在 MVP 中,视图和呈现器都通过接口相互通信,在这种情况下,呈现器接口不应受到实现细节的影响,而应仅公开它们能够执行的操作。
通常使用 Java,我们创建一个 *Contract
接口来处理 View 和 Presenter 之间的交互,喜欢:
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,那么您迟早会遇到问题。
例如,想象一个呈现器异步获取数据并将其缓存在内存中:
- 视图调用呈现器方法
fetchData()
。 - 提交者调用合约的
showLoading()
方法。 - (一段时间过去了)
- 演示者调用合约的
hideLoading()
和showData(data)
方法。 - 用户再次互动并触发
fetchData()
- 演示者使用缓存数据调用
showData()
在这种情况下,如果我们使用 lambda 而不是契约,我们将需要在同一方法中请求两个不同的 lambda:一个用于缓存,一个用于缓存。 我们也正在将视图实现耦合到呈现器,将来呈现器接口的另一个实现可能不需要这两个 lambda,因为逻辑已经改变。
重要的是要记住,在理想情况下,在 MVP 中,视图和呈现器都通过接口相互通信,在这种情况下,呈现器接口不应受到实现细节的影响,而应仅公开它们能够执行的操作。