一个使用 MVP 模式的简单图片获取 Android 应用





0/5 (0投票)
一个使用 MVP 模式的简单图片获取应用
引言
ImgurDner 是一款实验性的Android应用,用于从imgur.com下载热门图片。它采用了流行的MVP,即 Model View & Presenter 模式。
背景
虽然使用设计模式并不是开发移动应用的先决条件,但像MVC或MVP这样的架构模式有助于实现代码的关注点分离:区分负责视图的模块和负责业务逻辑的模块;建立GUI和后端数据之间有效的通信渠道。此外,单元测试也变得更容易,代码的可读性和可维护性也明显增强。
使用代码
为了进行一个简洁明了的演示,作者将代码保持简单,以便读者可以专注于代码的架构方面,从而理解在Android编程中使用MVP模式。
在MVP模式中,Presenter充当View和Model之间的“中间人”。它与View模块建立双向通信:从View获取Model请求的输入;同时,从Model检索结果并直接通过View的方法更新GUI(这是MVP与MVC模式的一个显著特征)。
该项目包含五个主要的Java文件
- DownloadActivity 和 DownloadFragment,这两个文件是View模块(尽管这主要是Fragment的工作。Android建议使用Fragment而不是Activity来处理UI);
- DownloadContract,一个包含View子接口和Presenter接口的接口;
- DownloadPresenter,Presenter接口的实现,充当View和Model之间的联络人
- ImgurService,一个符合Retrofit HTTP客户端框架协议的接口类,用于方便和异步的Web服务访问。
DownloadActivity.java 负责创建Presenter的实例并将引用传递给Fragment组件;Activity类还负责将Fragment(这是一个View的实现)传递给Presenter。通过完成这两个步骤,View和Presenter现在拥有双向通信。请注意,MVP和MVC模式之间的一个区别在于,在MVP中,Presenter可以通过View引用操作UI渲染。
@Override protected void onCreate(Bundle savedInstanceState) { ... //retrieve the reference to the fragment DownloadFragment downloadFragment = (DownloadFragment)getSupportFragmentManager().findFragmentById(R.id.contentFrame); if(downloadFragment == null){ downloadFragment = DownloadFragment.newInstance(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(R.id.contentFrame, downloadFragment); transaction.commit(); } //crate a presenter downloadPresenter = new DownloadPresenter(downloadFragment); //pass the view reference to the presenter downloadFragment.setPresenter(downloadPresenter); //pass the presenter reference to the view } ...
在MVP模式中使用Contract接口是很常见的做法,它由两个子接口组成。
- View接口。普通的Android Fragment类将实现此接口。
- Presenter接口,其中包括基本的Presenter功能。任何具体的Presenter类都至少会实现此接口。
public interface DownloadContract { interface View extends BaseView<presenter> { } interface Presenter extends BasePresenter { } } public interface BasePresenter { void start(); } public interface BaseView<T> { void setPresenter(T presenter); }</presenter>
具体的Presenter类负责从Web服务获取数据。在这种情况下,我们使用imgur.com的API来访问其丰富的图片存储库。
为了访问imgur的Web服务,我们使用Retrofit HTTP客户端框架。下面显示了简要步骤
首先,我们定义一个带有Web服务URL的接口
public interface ImgurService { String URL = "https://api.imgur.com/3/gallery/hot/viral/0.json"; @Headers({ "Authorization: Client-ID XXXXXXXXX", "User-Agent: XXXXXXXXXXXXXXXXXXXXXXXXX" }) @GET("/") void getAllImages(Callback<Image> cb); }
然后,我们按照Retrofit的编码约定检索数据,一旦成功,Presenter调用View的方法来更新UI
ImgurService restInterface = new RestAdapter.Builder().setEndpoint(ImgurService.URL).build().create(ImgurService.class); restInterface.getAllImages(new retrofit.Callback<Image>() { @Override public void success(Image model, retrofit.client.Response response) { List<Datum> images = model.getData(); for(Datum img : images){ Log.d(TAG, img.getLink()); } List<Datum> jpgImgs = Stream.of(images).filter(p -> p.getLink().contains(".jpg")||p.getLink().contains(".gif")).collect(Collectors.toList()); ImageRepo.newInstance().setImages(jpgImgs); ((DownloadFragment)mDownloadView).updateUI(); ((DownloadFragment)mDownloadView).stopSpin(); } @Override public void failure(RetrofitError error) { Log.e(TAG, error.getMessage()); } });
请注意:像Datum或Image这样的类是从JSON流转换而来的Java类(imgur Web服务使用的数据格式)。处理Java对象比解析原始JSON流对开发人员来说更舒服。这种JSON<->Java对象转换被称为Marshalling/Unmarshalling,可以通过Jackson等技术实现。
等等,虽然我有一个更好的主意,请按照这两个简单的步骤
关注点
- MVP模式用于关注点分离;
- 该应用从imgur的Web服务获取图像数据;
- Retrofit HTTP客户端框架用于数据获取目的;
- Picasso图像库用于图像渲染。
如何使用代码
这很容易。启动Android Studio,加载下载的源代码并点击“运行”
![]() | ![]() |
参考
历史
- 2017年7月7日,初始版本