我的 Android 开发实战经验总结 (2)

为什么要抽象依赖于第三方框架呢?这里和第1点是互相照应的,就是降低我们对具体某个框架的依赖性,从而方便我们快速切换到不同的框架去。说到这里,你可能觉得很抽象,那我直接举一个加载图片的例子好了。

假设你当前为项目引入一个加载图片的框架 —— Android-Universal-Image-Loader,最简单的做法就是加入相应的依赖包后,在任何需要加载图片的地方写上下面这样的代码段。

ImageLoader imageLoader = ImageLoader.getInstance(); // Get singleton instance // Load image, decode it to Bitmap and display Bitmap in ImageView (or any other view // which implements ImageAware interface) imageLoader.displayImage(imageUri, imageView); // Load image, decode it to Bitmap and return Bitmap to callback imageLoader.loadImage(imageUri, new SimpleImageLoadingListener() { @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { // Do whatever you want with Bitmap } });

这种做法最简单粗暴,但是带来的问题也最严重的。如果我有几十上百个地方都这么写,而在某一天,我听说Facebook出了个神器 Fresco,想要换掉 Android-Universal-Image-Loader ,你就会发现你需要丧心病狂的去改动几十上百个地方的代码,不仅工作量大,而且还容易出错。造成这样的原因,就在于项目和加载图片的框架之间形成了强耦合,而实际上,项目本身不应该知道我具体用了哪个加载图片的框架。

正确的方式,应该是对框架做一个抽象的封装,以应对未来发生的变化,我直接举自己的开源项目 AndroidAlbum 中的一种封装做法好了。

我的 Android 开发实战经验总结

AndroidAlbum

大致代码如下:

//1、声明 ImageLoaderWrapper 接口,定义一些抽象的加载接口方法 public interface ImageLoaderWrapper { /** * 显示 图片 * * @param imageView 显示图片的ImageView * @param imageFile 图片文件 * @param option 显示参数设置 */ public void displayImage(ImageView imageView, File imageFile, DisplayOption option); /** * 显示图片 * * @param imageView 显示图片的ImageView * @param imageUrl 图片资源的URL * @param option 显示参数设置 */ public void displayImage(ImageView imageView, String imageUrl, DisplayOption option); /** * 图片加载参数 */ public static class DisplayOption { /** * 加载中的资源id */ public int loadingResId; /** * 加载失败的资源id */ public int loadErrorResId; } } // 2、将 UniversalAndroidImageLoader 封装成继承 ImageLoaderWrapper 接口的 UniversalAndroidImageLoader , //这里代码有点长,感兴趣可以查看项目源码中的实现 https://github.com/D-clock/AndroidAlbum // 3、做一个ImageLoaderFactory public class ImageLoaderFactory { private static ImageLoaderWrapper sInstance; private ImageLoaderFactory() { } /** * 获取图片加载器 * * @return */ public static ImageLoaderWrapper getLoader() { if (sInstance == null) { synchronized (ImageLoaderFactory.class) { if (sInstance == null) { sInstance = new UniversalAndroidImageLoader();//<link>https://github.com/nostra13/Android-Universal-Image-Loader</link> } } } return sInstance; } } //4、在所有需要加载图片的地方作如下的调用 ImageLoaderWrapper loaderWrapper = ImageLoaderFactory.getLoader(); ImageLoaderWrapper.DisplayOption displayOption = new ImageLoaderWrapper.DisplayOption(); displayOption.loadingResId = R.mipmap.img_default; displayOption.loadErrorResId = R.mipmap.img_error; loaderWrapper.displayImage(imagview, url, displayOption);

这样一来,切换框架所带来的代价就会变得很小,这就是不直接依赖于框架所带来的好处。当然,以上只是我比较简单的封装,你也可以进行更加细致的处理。

小结:预留变更,不强耦合于第三方框架

4.从 MVC 到 MVP

说实话,在没接触 MVP 的架构之前,一直都是使用 MVC 的模式进行开发。而随着项目越来越大,Activity或者 Fragment里面代码越来越臃肿,看的时候想吐,改的时候想屎...这里撇开其他各种各样的架构不谈,只对比MVC 和 MVP 。

我的 Android 开发实战经验总结

MVC

View:布局的xml文件

Controller:Activity、Fragment、Dialog等

Model:相关的业务操作处理数据(如对数据库的操作、对网络等的操作都应该在Model层里)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzsjgj.html