RoboGuice 3.0 (一)入坑篇
RoboGuice是什么?
一个Android上的依赖注入框架。
依赖注入是什么?
从字面理解,这个框架做了两件事情,第一是去除依赖,第二是注入依赖。简单理解就是,将对象的初始化委托给一个容器控制器,即去除依赖,再从容器控制器中构建依赖,注入回原本的对象中,即注入依赖。
依赖注入的好处是对象不需要在乎其依赖的初始化,使代码变得无比简洁。
一.接入
在build.grade中添加依赖
dependencies {
provided 'org.roboguice:roboblender:3.0.1'
compile 'org.roboguice:roboguice:3.0.1'
}
二.视图注入
接触依赖注入后,最方便的可能就是视图的注入了,将之前成片的findViewById的代码省去,Activity中的代码量完成了史上第一次大扫除。
视图注入分三个步骤:
- 继承自RoboGuice的RoboActivity 当然RoboFragmentActivity也可以
- 为Activity加入content view(setContentView也可以使用注解来实现)
- 使用@InjectView来注入视图
@ContentView(R.layout.activity_main)
public class MainActivity extends RoboFragmentActivity {
@InjectView(R.id.text_test)
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView.setText("hello there!");
}
}
由此可见,视图注入大大简化了Activity中的代码量。
同理 ,Fragment也是一样的。需要注意的是,视图注入需要在onViewCreated后使用。
public class AFragment extends RoboFragment {
@InjectView(R.id.fragment_text)
TextView textView;
public static AFragment newInstance() {
return new AFragment();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.a_fragment, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
textView.setText("Hi there!");
}
}
三.资源注入
RoboGuice除了提供了视图注入,还提供了资源的注入。
比如String资源、color资源、Animation资源等。
@ContentView(R.layout.activity_main)
public class MainActivity extends RoboFragmentActivity {
@InjectView(R.id.text_test)
TextView textView;
@InjectResource(R.string.app_name)
String appName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView.setText(appName);
}
}
四.系统服务注入
在Activity中可以注入各种系统服务,比如震动、通知管理。
完整的列表在这:https://github.com/roboguice/roboguice/wiki/Provided-Injections
这样我们不用再去写烦人的getSystemService这种代码。
@ContentView(R.layout.activity_main)
public class MainActivity extends RoboFragmentActivity {
@Inject
Vibrator vibrator;
@Inject
NotificationManager notificationManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
vibrator.vibrate(500L);
notificationManager.cancelAll();
}
}
五.对象注入
对象的注入最大程度的完成了代码的解耦工作。也是类似框架中上手最慢的。
想象一个场景,比如在Activity中用户判断登录状态,我们不需要在乎UserInfo是如何初始化的,只在乎得到用户是否登陆的状态。
结合实际情况,举个例子。这是一个用来储存用户信息的model。
public class UserInfo {
private String userId;
private String token;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public boolean isLogin(){
return !TextUtils.isEmpty(token);
}
}
使用注解注入UserInfo,RoboGuice会帮我们完成初始化工作,初始化时调用UserInfo的默认构造方法。
这样在没有写userInfo = new UserInfo()我们便操作了对象。
@ContentView(R.layout.activity_main)
public class MainActivity extends RoboFragmentActivity {
@Inject
UserInfo userInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
userId = sharedPreferences.getString("userId", "");
token = sharedPreferences.getString("token", "");
String userId = sharedPreferences.getString("userId", "");
String token = sharedPreferences.getString("token", "");
userInfo.setUserId(userId);
userInfo.setToken(token);
}
}
再然而onCreate内部的取用户信息的代码确实很丑陋,我们需要在Activity中完成与页面不相关的初始化工作,核心原因是我们依赖了Activity中的Context。这就相当于,如果对象中的成员初始化时需要对象的一些属性,我们很难巧妙的将属性交给容器管理着负责初始化成员。
那么又该如何处理这么丑陋的代码呢。
RoboGuice提供了更让人欣喜的功能,将对象中的成员初始化需要的属性封装起来,提交给容器管理者,这样当依赖对象属性的成员初始化过程就可以完全脱离对象,在成功后注入回对象即可。
Talk is cheap! Show me the code.
在RoboGuice的Activity中,容器管理者已经默认提供了的属性比如页面中的Context,这样当成员初始化时,可以使用@Inject来标记构造方法以用来告诉RoboGuice不使用默认构造方法进行初始化,当构造方法中的参数属性已经由Activity对象提交给容器管理者时,即容器管理者会使用该构造方法进行初始化。
我们经过改装,UserInfo和Activity是这样的。其中@ContextSingleton注解标示UserInfo随Context的生命周期销毁而销毁,如果这里改为@Singleton,那么UserInfo的生命周期将是整个应用的生命周期,如果两个Activity都使用了该注解,那么产生的对象将是同一个。
这里需要注意的是,如果@ContextSingleton使用不当,将造成内存泄露,这个以后会有例子说明。
@ContextSingleton
public class UserInfo {
private static final String TAG = "UserInfo";
private Context context;
private String userId;
private String token;
@Inject
public UserInfo(Context context) {
this.context = context;
init();
}
private void init() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
userId = sharedPreferences.getString("userId", "");
token = sharedPreferences.getString("token", "");
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public boolean isLogin(){
return !TextUtils.isEmpty(token);
}
public void saveUserInfo(String userId) {
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
editor.putString("userId", userId);
editor.apply();
}
}
@ContentView(R.layout.activity_main)
public class MainActivity extends RoboFragmentActivity {
@InjectView(R.id.text_test)
TextView textView;
@Inject
UserInfo userInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(userInfo.isLogin()){
textView.setText(userInfo.getUserId());
} else {
textView.setText("未登录");
}
}
}
至此,入坑篇告一段落,这篇主要说明了RoboGuice的视图、资源、系统服务、对象等注入,为开发带来便捷,同时也减少了模块的耦合性。
RoboGuice 3.0 (一)入坑篇的更多相关文章
- Dagger2 (一) 入坑篇
为什么是Dagger2 为了更好的了解Dagger2,请先阅读RoboGuice篇了解依赖注入. 官方文档称,依赖注入这种技术已经在存在多年了,为什么Dagger2要造轮子? Dagger2是第一个全 ...
- mybatis(1):入坑篇
依赖 <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artif ...
- 【Mysql MHA】CentOS7.6+Mysql8.0.16 入坑
1.防火墙 firewall-cmd --add-port=/tcp --permanent firewall-cmd --reload 2.SELINUX sed -i 's/SELINUX=enf ...
- vuex 入坑篇
Vuex 是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 这个状态自管理应用包含 ...
- web前端入坑第五篇:秒懂Vuejs、Angular、React原理和前端发展历史
秒懂Vuejs.Angular.React原理和前端发展历史 2017-04-07 小北哥哥 前端你别闹 今天来说说 "前端发展历史和框架" 「前端程序发展的历史」 「 不学自知, ...
- web前端入坑第二篇:web前端到底怎么学?干货资料! 【转】
http://blog.csdn.net/xllily_11/article/details/52145172 版权声明:本文为博主[小北]原创文章,如要转载请评论回复.个人前端公众号:前端你别闹,J ...
- Vue入坑第一篇
写在前面的话:文章是个人学习过程中的总结,为方便以后回头在学习.文章中会参考官方文档和其他的一些文章,示例均为亲自编写和实践,若有写的不对的地方欢迎大家和我一起交流. 一.前言 本篇作为vue入门的一 ...
- Vue2.0史上最全入坑教程(下)—— 实战案例
书接上文 前言:经过前两节的学习,我们已经可以创建一个vue工程了.下面我们将一起来学习制作一个简单的实战案例. 说明:默认我们已经用vue-cli(vue脚手架或称前端自动化构建工具)创建好项目了 ...
- RxJava+RxAndroid+MVP入坑实践(基础篇)
转载请注明出处:http://www.blog.csdn.net/zhyxuexijava/article/details/51597230.com 前段时间看了MVP架构和RxJava,最近也在重构 ...
随机推荐
- Attach Volume 操作(Part II) - 每天5分钟玩转 OpenStack(54)
上一节我们讨论了 attach volume 操作中 cinder-api 的工作,本节讨论 cinder-volume 和 nova-compute 如何将 volume attach 到 Inst ...
- Form authentication(表单认证)问题
前言 最近在做ASP.NET MVC中表单认证时出了一些问题,特此记录. 问题 进行表单认证时,在 PostAuthenticateRequest 事件中从Cookie值中解密票据.如下: prote ...
- AngularJS之Directive(三)
前言 angular核心部分如下图几大块,最重要的莫过于指令这一部分,本文将重点讲解指令这一部分,后续笔者将通过陆续的学习来叙述其他如:factory.service等,若有叙述错误之处,欢迎各位指正 ...
- ORA-00257 archiver error 处理思路
1.首先查下oerr给出的简要说明 2.查询V$RECOVERY_AREA_USAGE信息 3.根据实际空间剩余情况先适当增加归档目录的大小,保证先恢复业务 4.查看备份是否存在问题 1.首先查下oe ...
- Oracle Recovery 01 - 常规恢复之完全恢复
背景:这里提到的常规恢复指的是数据库有完备可用的RMAN物理备份. 实验环境:RHEL6.4 + Oracle 11.2.0.4 DG primary. 一.常规恢复之完全恢复:不丢失数据 1.1 单 ...
- 【十大经典数据挖掘算法】k-means
[十大经典数据挖掘算法]系列 C4.5 K-Means SVM Apriori EM PageRank AdaBoost kNN Naïve Bayes CART 1. 引言 k-means与kNN虽 ...
- QTableView中修改某个单元格或者行或者列内容颜色
QTableView的单元格内容实现还是继承了TableViewModel类的data(const QModelIndex &index, int role) const函数,那个设置颜色的问 ...
- MS SQL 字符拆分存处理
MS SQL Server没有split()函数,但是我们可以写一个Table-valued Functions定义函数[dbo].[udf_SplitStringToTable] : CREATE ...
- iOS学习笔记——AutoLayout的约束
iOS学习笔记——AutoLayout约束 之前在开发iOS app时一直以为苹果的布局是绝对布局,在IB中拖拉控件运行或者直接使用代码去调整控件都会发上一些不尽人意的结果,后来发现iOS在引入了Au ...
- WPF DataGrid 鼠标双击选中的DataGridRow及Row数据
设置DataGrid的MouseDoubleClick事件 代码 //DataGrid鼠标双击事件 Private void dataGrid_MouseDoubleClick(object send ...