这里有一些如何使用Mosby来建立一个基于MVP的架构的简单的例子。我们假设你已经知道“MVP - passive view”,如果不是,你应该考虑阅读 Mosby翻译(三) : MVP原理,以便在继续之前了解MVP的基本知识。
Hello MVP World
在这个非常简单的例子中,我们假设view要显示一个TextView,这个TextView显示“Hello”和一个随机数字,或者“Goodbye”和一个随机数字。如果显示“Hello”,则文字颜色将变为红色,如果是“Goodbye”则将以蓝色文字显示。生成问候文本是在一个AsyncTask
里完成的,我们假设生成问候文本(随机数计算并连接在问候文本的结尾)是耗CPU的,并且需要2秒。
1 | // "Business logic" component |
1 | // View interface |
1 | // The presenter that coordinates HelloWorldView and business logic (GreetingGeneratorTask) |
1 | // Called when Activity gets destroyed, so cancel running background task |
1 | public class HelloWorldActivity extends MvpActivity<HelloWorldView, HelloWorldPresenter> |
正如你在HelloWorldActivity
中所看到的,只包含与UI组件相关的代码。没有业务逻辑,没有1000多行乱七八糟代码的Activity。通过View(HelloWorldActivity),Presenter(HelloWorldPresenter)和业务逻辑(GreetingGeneratorTask)之间的明确分离,您可以编写可维护,松耦合和可测试的代码。这就是MVP的全部内容。
LCE例子
下面这个例子稍微复杂一些,更接近真实世界的应用程序。假设我们想要在RecyclerView
中显示一个国家列表。国家列表从Web服务(异步)加载,并且需要几秒钟。我们将使用Retrofit
作为http库。加载时我们要显示一个ProgressBar
。如果发生错误,我们希望显示错误消息。此外,我们要使用一个SwipeRefreshLayout
,使用户可以刷新国家列表。我们把这类View叫做LCE-View
(Loading-Content-Error),因为View有三种状态:显示加载,显示内容和显示错误视图。Mosby为这样的Views提供了一个模板:MvpLceActivity
和MvpLceFragment
。这些模板的基类中会处理更改视图状态的操作(使用淡入淡出的动画)。
1 | // Business logic: We use Retrofit to load a list of Countries from a web service |
1 | // View interface |
1 | class CountriesPresenter extends MvpBasePresenter<CountriesView> { |
1 | public class CountriesFragment |
LCE ViewState示例
在之前的LCE示例中如果用户旋转屏幕,会发生什么?一个新的Fragment被创建,再次显示ProgressBar,即使在屏幕方向改变之前,我们已经显示了数据(国家列表)。Mosby提供了一个称为ViewState
的功能来处理屏幕方向的变化。查看ViewState部分来查看更多和其工作原理。在这个“入门”部分,我们只是想展示如何将ViewState支持添加到之前的LCE示例,以便您的应用程序仍然处于屏幕方向更改之前的状态,即在竖屏时显示国家列表,在横屏时仍然显示国家列表。我们所要做的就是继承MvpLceViewStateFragment
而不是MvpLceFragment
,并且实现createViewState()
和getData()
:
1 | public class CountriesFragment |
请注意,Activities和ViewGroup也支持ViewState功能。
Kotlin示例
Kotlin是Android开发中的新希望。从Mosby 2.0开始支持Kotlin。在这个例子中,我们将展示一个非常基本的LCE示例,在这个例子中,我们生成(异步)超级英雄列表,并将其显示在RecyclerView中。
1 | // Business logic: AsyncTask generates list of heroes and invokes successful lambda or error lambda as "callback" |
1 | interface HeroesView : MvpLceView<List<Hero>> { |
1 | public class HeroesPresenter : MvpBasePresenter<HeroesView> () { |
1 | public class HeroesActivity : HeroesView, MvpLceViewStateActivity<SwipeRefreshLayout, List<Hero>, HeroesView, HeroesPresenter>(), SwipeRefreshLayout.OnRefreshListener { |