什么是依赖注入?

依赖是指一个对象持有其他对象的引用。依赖注入则是将这些依赖对象传递给被依赖对象,而不是被依赖对象自己创建这些对象。 
public class MyClass{private AnotherClass mAnotherObject;public MyClass(){mAnotherObject = new AnotherClass();}
}

通过传递对象的方式,所传递对象的更改不会影响代码。 
public class MyClass{private MyInterface mAnotherObject;public MyClass(MyInterface anotherObject){mAnotherObject = anotherObject;}
}

  依赖注入可以简化代码编写,并提供一个可适配的环境,方便进行单元测试以及功能模块的配置。

开发中可能会遇到这样的麻烦。

我们将通过一个例子来理解依赖注入的应用场景:某Android应用需要一个列表来显示用户的好友。 
public class FriendListFragment{private FriendListAPI mFriendListAPI;......public FriendListFragment(){mFriendListAPI = new FriendListAPI();}private void getFriendList(){mFriendListAPI.getFriendList(new Callback(){public void onSuccess(List<User> list){......}......});}
}public class FriendListAPI{private OkHttpClient mHttpClient;public FriendListAPI(){mHttpClient= new OkHttpClient();//接下来各种Http配置
          ......}
}

  代码写好了,运行程序试试。可是,后台API没有准备好或者没有数据怎么办?自己添点测试数据试试吧。在FriendListFragment里面添加一个生成测试数据的方方法buildTestData(),并替换getFriendList()方法。等后台API准备好后再改回来。

我们想测试网络有延迟或错误的时候,程序是否会出现异常。这需要通过配置OkHttpClient参数来实现测试场景,于是又要更改FriendListAPI中相关HttpClient配置代码,测试完后再修改回来。
这样对代码进行多次修改,很容易出错。因此,对于多次使用的模块,我们可以通过注入的方式,将引用传入需要使用的类中,而不是自己创建。通过编写两个API,一个是直接请求后台数据,另一个则只是一些静态测试数据。需要测试的时候注入可生成测试数据的API,测试完后则切换为正式API。 
public class FriendListFragment{private FriendListAPI mFriendListAPI;......public FriendListFragment(FriendListAPI friendListAPI){mFriendListAPI = friendListAPI;}
}public class FriendListAPI{private OkHttpClient mHttpClient;public FriendListAPI(HttpClient okHttpClient){mHttpClient= okHttpClient;......}
}

  现在引入一个稍微复杂的场景,更多的Fragment需要使用FriendListAPI,我们需要在两个不同的地方进行注入,因此产生了许多重复代码。

因此,我们需要一个容器,它知道什么地方需要注入,注入什么样的对象。 

Dagger解决方案。

这里简单的展示轻量级依赖注入库Dagger实现的注入。
首先定义模块:
public class MyModule{@Provides @Singleton OkHttpClient provideOkHttpClient(){//这里可进行各种Http配置return new OkHttpClient();}@Provides @Singleton FriendListAPI provideFriendListAPI(){return newFriendListAPI();}
}

  初始化模块以及依赖对象图。

public class MyApplication extends Application{private ObjectGraph graph;@Override public void onCreate() {super.onCreate();graph = ObjectGraph.create(getModules().toArray());}protected List<Object> getModules() {return Arrays.asList(new MyModule(this));}public void inject(Object object) {graph.inject(object);}
}

  最后添加注入点并进行注入。

public abstract class BaseActivity extends FragmentActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);((MyApplication) getApplication()).inject(this);}
}public class FriendListFragment{@Inject FriendListAPI mFriendListAPI;......
}public class FriendListAPI{@Inject OkHttpClient mHttpClient;......
}

  如需进行单元测试,或使用可生成测试数据的模拟API,则再编写一个模块,在初始模块和依赖对象图时替换即可。

现有的依赖注入性能?

依赖注入虽能简化代码编写,方便单元测试,可是由于当前基于反射的依赖注入框架(Guice、RoboGuice)性能并不好。原因是他们会在程序运行的时候需要扫描代码中的注解,并需要花费内存映射到内存中。
这里推荐使用Dagger是因为它使用了编译时注解,也就是说在编译代码的时候,Dagger就已经完成传统依赖注入框架在运行时所执行的任务。

什么时候需要依赖注入?

当你需要将配置数据注入到一个或多个模块时。在开发过程中前端访问后台服务器地址会分为测试服务器和正式服务器,以及各种第三方分享key和ID,依赖注入都是非常好的选择。
当需要将同一依赖注入到多个模块时。如加载图片以及图片存储管理组件(Picasso, Android-Universal-Image-Loader)。
当需要对同一依赖注入不同的实现时。为方便开发和单元测试,后台API可有正式API和模拟API,通过依赖注入方便切换环境。
当同一模块需要注入不同的配置时。

参考资料:

http://square.github.io/dagger/

转载于:https://www.cnblogs.com/hellsong/p/4463569.html

Android开发中依赖注入的应用相关推荐

  1. 在android开发中使用multdex的方法-IT蓝豹为你整理

    在android开发中使用multdex的方法-IT蓝豹为你整理 Android系统在安装应用时,往往需要优化Dex,而由于处理工具DexOpt对id数目的限制,导致其处理的数目不能超过65536个, ...

  2. dagger android,在Android开发中使用Dagger2的方法

    在Android开发中使用Dagger2的方法 发布时间:2020-12-08 17:12:38 来源:亿速云 阅读:236 作者:Leah 在Android开发中使用Dagger2的方法?相信很多没 ...

  3. Swift中依赖注入的解耦策略

    原文地址:Dependency Injection Strategies in Swift 简书地址:Swift中依赖注入的解耦策略 今天我们将深入研究Swift中的依赖注入,这是软件开发中最重要的技 ...

  4. Android开发中使用七牛云存储进行图片上传下载

    Android开发中的图片存储本来就是比较耗时耗地的事情,而使用第三方的七牛云,便可以很好的解决这些后顾之忧,最近我也是在学习七牛的SDK,将使用过程在这记录下来,方便以后使用. 先说一下七牛云的存储 ...

  5. 在 Android 开发中使用 Kotlin 协程 (一) -- 初识 Kotlin 协程

    前言 最近在研究 Kotlin 协程,发现功能真的超级强大,很有用,而且很好学,如果你正在或计划使用 Kotlin 开发 Android,那么 Kotlin 协程你一定不能错过! 协程是什么? 我们平 ...

  6. android开发模式,Android开发中无处不在的设计模式

    Android开发中无处不在的设计模式――单例模式 Android开发中无处不在的设计模式――Builder模式 前面介绍了单例模式和Builder模式,有兴趣的见上面两个链接,这篇文章侧重介绍1下视 ...

  7. Android开发中常见的设计模式

    对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次.而在android开发中,必要的了解一些设计模式又是非常有必要的.对于想系统的学习设计模式的 ...

  8. Android开发中EditText获得焦点弹出输入框改变屏幕布局的问题

    在Android开发中,比较头疼的问题就是EditText总是已启动就获得焦点并弹出输入框,感觉很是不爽.而且,因为输入框的弹出,导致屏幕布局获得改变,有些空间被挤压到一起,很是难看,所以,我就上网搜 ...

  9. android最佳开发实现_在android开发中使用可访问性最佳做法

    android最佳开发实现 As you know, accessibility is about building products that everyone can use easily and ...

最新文章

  1. 趋势科技实习面试后感
  2. linux下yum包更新不了
  3. 自己写getElementsByClass()方法
  4. OpenCV实现连通域
  5. java 写入环境变量_Java环境变量配置 - import_key的个人空间 - OSCHINA - 中文开源技术交流社区...
  6. c#物联网_C# 基础知识系列- 16 开发工具篇
  7. MaxCompute Studio使用心得系列6——一个工具完成整个Python UDF开发
  8. mongodb常用操作命令(待续)
  9. 华为帮助摩洛哥成为全球第一个5G全覆盖的国家
  10. 两次称量误差多少为恒重_双台子100吨二手散装罐回收价格多少
  11. firefox如何载入json文件_Firefox在书签工具栏中推隐藏“其他书签”文件夹功能
  12. k8s与日志--journalbeat源码解读
  13. oracle建表语句6,Oracle建表语句
  14. 【计算机网络】计算机网络基础知识笔记
  15. 加权平均数的例子_EXCEL 加权平均数的计算
  16. python seaborn教程_Seaborn官方教程中文教程(一)
  17. kubernetes 开发必须要知道的知识点—— API Group
  18. Y7000P电池0%解决办法
  19. const violate
  20. EditPlus设置保存时不生成bak文件

热门文章

  1. 2017年php还能火多久,PHP还会火吗?
  2. 税收分类编码2020_增值税开票系统你会吗?2020最新开票(金税盘版)图文教程详细版...
  3. JavaScript高级之ES5 中的新增方法
  4. 指令系统——数据存放、指令寻址(详解)
  5. LeetCode LCP 30. 魔塔游戏(优先队列)
  6. LeetCode 1749. 任意子数组和的绝对值的最大值(前缀和)
  7. LeetCode 1181. 前后拼接(哈希map)
  8. LeetCode 第 30 场双周赛(477/2545,前18.7%,第2次全部通过)
  9. 数据结构--栈--浏览器前进后退应用
  10. burp爆破线程设置多少_你知道线程池创建多少线程比较合理吗?