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 (一)入坑篇的更多相关文章

  1. Dagger2 (一) 入坑篇

    为什么是Dagger2 为了更好的了解Dagger2,请先阅读RoboGuice篇了解依赖注入. 官方文档称,依赖注入这种技术已经在存在多年了,为什么Dagger2要造轮子? Dagger2是第一个全 ...

  2. mybatis(1):入坑篇

    依赖 <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artif ...

  3. 【Mysql MHA】CentOS7.6+Mysql8.0.16 入坑

    1.防火墙 firewall-cmd --add-port=/tcp --permanent firewall-cmd --reload 2.SELINUX sed -i 's/SELINUX=enf ...

  4. vuex 入坑篇

    Vuex 是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 这个状态自管理应用包含 ...

  5. web前端入坑第五篇:秒懂Vuejs、Angular、React原理和前端发展历史

    秒懂Vuejs.Angular.React原理和前端发展历史 2017-04-07 小北哥哥 前端你别闹 今天来说说 "前端发展历史和框架" 「前端程序发展的历史」 「 不学自知, ...

  6. web前端入坑第二篇:web前端到底怎么学?干货资料! 【转】

    http://blog.csdn.net/xllily_11/article/details/52145172 版权声明:本文为博主[小北]原创文章,如要转载请评论回复.个人前端公众号:前端你别闹,J ...

  7. Vue入坑第一篇

    写在前面的话:文章是个人学习过程中的总结,为方便以后回头在学习.文章中会参考官方文档和其他的一些文章,示例均为亲自编写和实践,若有写的不对的地方欢迎大家和我一起交流. 一.前言 本篇作为vue入门的一 ...

  8. Vue2.0史上最全入坑教程(下)—— 实战案例

    书接上文 前言:经过前两节的学习,我们已经可以创建一个vue工程了.下面我们将一起来学习制作一个简单的实战案例. 说明:默认我们已经用vue-cli(vue脚手架或称前端自动化构建工具)创建好项目了 ...

  9. RxJava+RxAndroid+MVP入坑实践(基础篇)

    转载请注明出处:http://www.blog.csdn.net/zhyxuexijava/article/details/51597230.com 前段时间看了MVP架构和RxJava,最近也在重构 ...

随机推荐

  1. TSQL语句练习题

    1. 查询Student表中的所有记录的Sname.Ssex和Class列. select Sname,Ssex,Class from Student 2. 查询教师所有的单位即不重复的Depart列 ...

  2. Java基本语法练习

    1.编写程序,求100以内的全部素数. 实验源码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class F ...

  3. 使用openfiler设置SMB/CIFS共享总是不通过的一例与解决办法

    最近使用openfiler进行空闲存储的集中化管理与多主机节点共享,等设置到了SMB/CIFS的时候总是通过不了,前提需要开启的LDAP内建在openfiler也都开启并设置好了,但就是无法通过&qu ...

  4. jQuery打造智能提示插件二(可编辑下拉框)

    在上一篇 jQuery打造智能提示插件 上改进,增加下拉按钮,修复点击下拉区域外不隐藏BUG 效果 下拉按钮素材: js封装,注意红色部分为BUG修复,然后传入boxwidth不带px: /* /// ...

  5. jQuery方法position()与offset()区别

    参考别人写得比较明白的,红色部分为重点吧: 使用jQuery获取元素位置时,我们会使用position()或offset()方法,两个方法都返回一个包含两个属性的对象-左边距和上边距,它们两个的不同点 ...

  6. git log命令全解析,打log还能这么随心所欲!

    git log命令非常强大而好用,在复杂系统的版本管理中扮演着重要的角色,但默认的git log命令显示出的东西实在太丑,不好好打扮一下根本没法见人,打扮好了用alias命令拍个照片,就正式出道了! ...

  7. 原生js文字标签云上下滚动播放

    效果:http://hovertree.com/texiao/js/25/ 效果图: 代码如下: <!DOCTYPE html> <html> <head>< ...

  8. CSS3橙色的星球绕轨道公转动画

    效果:http://hovertree.com/texiao/css3/24/ 效果图: 代码如下: <!DOCTYPE html> <html lang="zh" ...

  9. iOS阶段学习第32天笔记(页面传值方法介绍)

    iOS学习(UI)知识点整理 一.界面传值方法 1.方法一  Block传值  通过SubView视图的Block向View视图传值改变View视图的背景色 实例代码: 1)SubViewContro ...

  10. Asp.net 面向接口可扩展框架之应用程序上下文作用域组件

    在团队中推广面向接口开发两年左右,成果总体来说我还是挺满意的,使用面向接口开发的模块使用Unity容器配置的功能非常稳定,便于共享迁移(另一个项目使用只需要复制配置和调用接口即可),如果再配合上DI那 ...