使用Roboguice依赖注入规划Android项目
前言
好久没写博客了,罪过啊~记事本里累积了不少东西,整理整理放上来。
关于依赖注入
通常博主开发项目时喜欢以Activity 、Service 等组件作为顶级层入口,辅以各类接口作为业务服务。Activity 主要负责维护界面相关的东西,及提供功能所需要的上下文环境,引入功能实现需要的接口。
这些接口的实例通过Roboguice进行注入。(当然你也可以完全不使用Roboguice,但还是建议保留接口注入的设计)。
关于Roboguice
项目地址:https://github.com/roboguice/roboguice .利用Roboguice可以较轻松的注入各种服务,它默认提供了各种android相关的注入如: injectView ,injectResource 等。
遗憾的是这里将不对Roboguice的使用详细讲解。想了解 Roboguice 的读者可以查看官网的Wiki 或参考:http://www.imobilebbs.com/wordpress/archives/2480
下载需要的包
项目创建
基本功能
项目仅包含一个Activity,界面上包含一个TextView和Button.点击Button 可查看当前时间。
通常我喜欢把数据相关的模块(db、sharepreferene、net、cache等)归类到Repository中,对上层而言就形成一个数据来源接口。
注意:没有哪一种设计是万能,需要根据最实际的情况,不断的进行权衡,最终选择较合适的系统设计,并且要做好睡着系统的成长需要变更设计的准备。
例如有的android程序比较简单,就完全不需要 IService 服务层。
项目包结构


使用静态类的实现方式
1 public class AndroidTimeRead {
2
3 public static TimeViewModel showTime() {
4 TimeViewModel model = new TimeViewModel();
5 model.setTime(String. valueOf(System.currentTimeMillis ()));
6 return model;
7 }
8
9 }
public class MainActivity extends Activity {
private TextView txtShowTime ;
private Button btnShow ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout. activity_main);
txtShowTime = (TextView) findViewById(R.id.txtShowTime);
btnShow = (Button) findViewById(R.id. btnShow);
btnShow.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
TimeViewModel viewModel = AndroidTimeRead. showTime();
txtShowTime.setText(viewModel.getTime());
}
});
}
}
另一个问题是:当你想对MainActivity 进行单元测试,你会发现非常困难,AndroidTimeRead 必须被包含进来,如果它还引用了其他的组件(如Db 或 net),那么这些组件也必须包含入内。 静态类型因为一直在内存中,如果它引用了其他类型,则被引用的对象CG无法回收。
改进
1 public class AndroidTimeRead {
2
3 private static class InstaceHolder{
4 public static AndroidTimeRead instance= new AndroidTimeRead();
5 }
6
7 public static AndroidTimeRead getInstance(){
8 return InstaceHolder.instance;
9 }
private AndroidTimeRead(){}
public TimeViewModel showTime() {
TimeViewModel model = new TimeViewModel();
model.setTime(String. valueOf(System.currentTimeMillis ()));
return model;
}
}
1 TimeViewModel viewModel = AndroidTimeRead. getInstance().showTime();调用修改
这里去掉了静态的方式,可是却没有解除直接依赖实现的问题。
关注行为
public interface ITimeService {
TimeViewModel showTime();
3 }
1 private ITimeService timeService ;
2 //提供注入点
3 public void setTimeService(ITimeService timeService) {
4 this.timeService = timeService;
5 }
6
7 @Override
8 protected void onCreate(Bundle savedInstanceState) {
9 super.onCreate(savedInstanceState);
setContentView(R.layout. activity_main);
txtShowTime = (TextView) findViewById(R.id.txtShowTime);
btnShow = (Button) findViewById(R.id. btnShow);
btnShow.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
TimeViewModel viewModel = timeService.showTime();
txtShowTime.setText(viewModel.getTime());
}
});
}
遗憾的是上面的程序不能正常运行,ITimeService 没有实例化。我们虽然提供了注入点,但是Activity 的生命周期由系统接管,我们无法直接使用。
事实上当你使用Roboguice 时也是需要继承自其提供的RoboActivity。
完成业务代码
在引入Roboguice 前先完成Demo的结构。添加ITimeRepository 和对应的实现,并让AndroidTimeRead 依赖 ITimeRepository。
public class TimeModel {
public long CurrentTime ;
}
public interface ITimeRepository {
TimeModel query();
}
public class TimeRepository implements ITimeRepository {
@Override
public TimeModel query() {
TimeModel model=new TimeModel();
model.CurrentTime=System. currentTimeMillis();
return model;
}
}
public class AndroidTimeRead implements ITimeService {
private ITimeRepository rep ;
public AndroidTimeRead(ITimeRepository rep) {
this.rep = rep;
}
public TimeViewModel showTime() {
TimeViewModel model = new TimeViewModel();
model.setTime( "现在的时间是" + String.valueOf( rep.query()));
return model;
}
}
引入Roboguice 应该放在哪里?
命名一个Infrastructure包,将需要的基础设施放置在此。
引入RoboActivity
1 public class MainActivity extends RoboActivity {
2
3 @InjectView(R.id.txtShowTime )
4 private TextView txtShowTime ;
5 @InjectView(R.id.btnShow )
6 private Button btnShow ;
7
8 @Inject
9 private ITimeService timeService ;
//提供注入点
public void setTimeService(ITimeService timeService) {
this.timeService = timeService;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout. activity_main);
btnShow.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
TimeViewModel viewModel = timeService.showTime();
txtShowTime.setText(viewModel.getTime());
}
});
}
public class RoboApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
RoboGuice. setBaseApplicationInjector(this, RoboGuice. DEFAULT_STAGE,
RoboGuice. newDefaultRoboModule(this), new TimeModule());
}
}
1 public class TimeModule implements Module {
2
3 @Override
4 public void configure(Binder binder) {
5 //顺序无关,在具体的Activity中 被创建
6 binder
7 .bind(ITimeService. class)
8 .to(AndroidTimeRead. class);
9 //.in(Singleton.class);//单件
binder.bind(ITimeRepository. class)
.to(TimeRepository. class);
}
}
AndroidTimeRead getAndroidTimeRead(ITimeRepository rep){
return new AndroidTimeRead(rep);
}
1 public class AndroidTimeReadProvider implements Provider<AndroidTimeRead> {
2
3 @Inject
4 ITimeRepository rep;
5
6 @Override
7 public AndroidTimeRead get() {
8
9 return new AndroidTimeRead( rep );
}
}
2 public void configure(Binder binder) {
3 //顺序无关,在具体的Activity中 被创建
4 binder
5 .bind(ITimeService. class )
6 .to(AndroidTimeRead. class );
7 //.in(Singleton.class);//单件
8
9 binder.bind(ITimeRepository. class )
.to(TimeRepository. class );
binder.bind(AndroidTimeRead. class )
.toProvider(AndroidTimeReadProvider. class );
}

引入注入框架需要的思考:
3、其他可选择的框架如 dagger
使用Roboguice依赖注入规划Android项目的更多相关文章
- 基于ABP模块组件与依赖注入组件的项目插件开发
注意,阅读本文,需要先阅读以下两篇文章,并且对依赖注入有一定的基础. 模块系统:http://www.cnblogs.com/mienreal/p/4537522.html 依赖注入:http://w ...
- 在 xunit 测试项目中使用依赖注入
在 xunit 测试项目中使用依赖注入 Intro 之前写过几篇 xunit 依赖注入的文章,今天这篇文章将结合我在 .NET Conf 上的分享,更加系统的分享一下在测试中的应用案例. 之所以想分享 ...
- MVC3+AutoFac实现程序集级别的依赖注入
1.介绍 所谓程序集级别的依赖注入是指接口和实现的依赖不使用配置文件或硬代码实现(builder.RegisterType<UserInfoService>().As<IU ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之九 || 依赖注入IoC学习 + AOP界面编程初探
更新 1.如果看不懂本文,或者比较困难,先别着急问问题,我单写了一个关于依赖注入的小Demo,可以下载看看,多思考思考注入的原理: https://github.com/anjoy8/BlogArti ...
- Ioc 器管理的应用程序设计,前奏:容器属于哪里? 控制容器的反转和依赖注入模式
Ioc 器管理的应用程序设计,前奏:容器属于哪里? 我将讨论一些我认为应该应用于“容器管理”应用程序设计的原则. 模式1:服务字典 字典或关联数组是我们在软件工程中学到的第一个构造. 很容易看到使 ...
- 【半小时大话.net依赖注入】(一)理论基础+实战控制台程序实现AutoFac注入
系列目录 第一章|理论基础+实战控制台程序实现AutoFac注入 第二章|AutoFac的常见使用套路 第三章|实战Asp.Net Framework Web程序实现AutoFac注入 第四章|实战A ...
- PHP 在Swoole中使用双IoC容器实现无污染的依赖注入
简介: 容器(container)技术(可以理解为全局的工厂方法), 已经是现代项目的标配. 基于容器, 可以进一步实现控制反转, 依赖注入. Laravel 的巨大成功就是构建在它非常强大的IoC容 ...
- Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之九 || 依赖注入IoC学习 + AOP界面编程初探
本文梯子 本文3.0版本文章 更新 代码已上传Github+Gitee,文末有地址 零.今天完成的绿色部分 一.依赖注入的理解和思考 二.常见的IoC框架有哪些 1.Autofac+原生 2.三种注入 ...
- Gin实现依赖注入
前言 依赖注入的好处和特点这里不讲述了,本篇文章主要介绍gin框架如何实现依赖注入,将项目解耦. 项目结构 ├── cmd 程序入口 ├── common 通用模块代码 ├── config 配置文件 ...
随机推荐
- Unbunt vi 编辑器键盘按键不正确的一次经历与解决方案
在 VMWare 上安装了 Ubuntu Server 14.04.1(这个默认没有安装 vim ) 我在配置网卡的时候,编辑得很心碎.键盘输入和平常vi的响应完全不一样.又不能用 SecureCRT ...
- 初试Nodejs——使用keystonejs创建博客网站2(修改模板)
上一篇(初试Nodejs——使用keystonejs创建博客网站1(安装keystonejs))讲了keystonejs的安装.安装完成后,已经具备了基本的功能,我们需要对页面进行初步修改,比如,增加 ...
- git & scp
git & scp command : git & scp git git 提交 git checkout/pull =====[在提交前校验远程是否有冲突] git add [< ...
- codeforces 446C DZY Loves Fibonacci Numbers 线段树
假如F[1] = a, F[2] = B, F[n] = F[n - 1] + F[n - 2]. 写成矩阵表示形式可以很快发现F[n] = f[n - 1] * b + f[n - 2] * a. ...
- c#输出、输入
//输出 Console.WriteLine("这是一行文字"); 自动回车的. Console.Write("Hello world"); 不带回车的. ...
- MyISAM和InnoDB索引区别
MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址.下图是MyISAM索引的原理图: 图8 这里设表一共有三列,假设我们以Col1为主键,则图8是一个MyISAM表 ...
- axure设置变量值
以登录框为例设置axure变量值 1.打开axure,打开新页面命名为login,拖入一个矩形背景,命名:登录背景图 2.拖入标签控件和输入框控件分别命名为用户名:.userName.密码:.pass ...
- CSS3制作各种形状图像
圆形-椭圆形-三角形-倒三角形=左三角形-右三角形-菱形-平行四边形- 星形-六角星形-五边形-六边形-八角形-心形-蛋形-无穷符号-消息提示框 不废话直接 html界面(亲测的) ------转自百 ...
- android书籍
教程 源码下载 高薪招聘 Cocos2d-x 博客 签到 视频教程 wiki 帖子 搜索 热搜:二维码定时器手电筒滑块斗地主书架定位买手机聊天游戏开发游戏股票查询机顶盒通话记录二维码扫描振动器 ...
- 1154. Easy sort
#include<iostream>#include<cmath>#include<iomanip>#include<algorithm>using n ...