使用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 可查看当前时间。
ITimeService 接口的详细实现类AndroidTimeReand则依赖于ITimeRepository(数据源),这样就从逻辑上划分出一个主要的三层。
通常我喜欢把数据相关的模块(db、sharepreferene、net、cache等)归类到Repository中,对上层而言就形成一个数据来源接口。
注意:没有哪一种设计是万能。须要依据最实际的情况,不断的进行权衡,终于选择较合适的系统设计,而且要做好睡着系统的成长须要变更设计的准备。
比如有的android程序比較简单。就全然不须要 IService 服务层。
项目包结构
使用静态类的实现方式
1 public class AndroidTimeRead {
3 public static TimeViewModel showTime() {
4 TimeViewModel model = new TimeViewModel();
5 model.setTime(String. valueOf(System.currentTimeMillis ()));
6 return model;
7 }
8
9 }
10
11 public class MainActivity extends Activity {
12
13 private TextView txtShowTime ;
14 private Button btnShow ;
15
16 @Override
17 protected void onCreate(Bundle savedInstanceState) {
18 super.onCreate(savedInstanceState);
19 setContentView(R.layout. activity_main);
20
21 txtShowTime = (TextView) findViewById(R.id.txtShowTime);
22 btnShow = (Button) findViewById(R.id. btnShow);
23 btnShow.setOnClickListener( new View.OnClickListener() {
24
25 @Override
26 public void onClick(View v) {
27 TimeViewModel viewModel = AndroidTimeRead. showTime();
28 txtShowTime.setText(viewModel.getTime());
29 }
30 });
31
32 }
33
34 }
但有两个明显的缺点,假设项目中大部分都是用了静态。那么面向OO的各种设计也就无法使用了。
还有一个问题是:当你想对MainActivity 进行单元測试,你会发现很困难。AndroidTimeRead 必须被包括进来,假设它还引用了其它的组件(如Db 或 net),那么这些组件也必须包括入内。 静态类型由于一直在内存中,假设它引用了其它类型,则被引用的对象CG无法回收。
改进
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 }
10
11 private AndroidTimeRead(){}
12
13 public TimeViewModel showTime() {
14 TimeViewModel model = new TimeViewModel();
15 model.setTime(String. valueOf(System.currentTimeMillis ()));
16 return model;
17 }
18
19 }
1 TimeViewModel viewModel = AndroidTimeRead. getInstance().showTime();调用改动
这里去掉了静态的方式,但是却没有解除直接依赖实现的问题。
关注行为
在这里样例中基本的行为就是showTime.
2 TimeViewModel showTime();
3 }
1 private ITimeService timeService ;
3 public void setTimeService(ITimeService timeService) {
4 this.timeService = timeService;
5 }
6
7 @Override
8 protected void onCreate(Bundle savedInstanceState) {
9 super.onCreate(savedInstanceState);
10 setContentView(R.layout. activity_main);
11
12 txtShowTime = (TextView) findViewById(R.id.txtShowTime);
13 btnShow = (Button) findViewById(R.id. btnShow);
14 btnShow.setOnClickListener( new View.OnClickListener() {
15
16 @Override
17 public void onClick(View v) {
18 TimeViewModel viewModel = timeService.showTime();
19 txtShowTime.setText(viewModel.getTime());
20 }
21 });
22
23 }
遗憾的是上面的程序不能正常执行。ITimeService 没有实例化。我们尽管提供了注入点。可是Activity 的生命周期由系统接管。我们无法直接使用。
其实当你使用Roboguice 时也是须要继承自其提供的RoboActivity。
完毕业务代码
在引入Roboguice 前先完毕Demo的结构。
加入ITimeRepository 和相应的实现。并让AndroidTimeRead 依赖 ITimeRepository。
1 public class TimeModel {
2 public long CurrentTime ;
3 }
4 public interface ITimeRepository {
5 TimeModel query();
6 }
@Override
public TimeModel query() {
TimeModel model= new TimeModel();
model.CurrentTime=System. currentTimeMillis();
return model;
}
}
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
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 ;
10 // 提供注入点
11 public void setTimeService(ITimeService timeService) {
12 this.timeService = timeService;
13 }
14
15 @Override
16 protected void onCreate(Bundle savedInstanceState) {
17 super.onCreate(savedInstanceState);
18 setContentView(R.layout. activity_main);
19
20 btnShow.setOnClickListener( new View.OnClickListener() {
21
22 @Override
23 public void onClick(View v) {
24 TimeViewModel viewModel = timeService.showTime();
25 txtShowTime.setText(viewModel.getTime());
26 }
27 });
28
29 }
2
3 @Override
4 public void onCreate() {
5 super.onCreate();
6 RoboGuice. setBaseApplicationInjector( this, RoboGuice. DEFAULT_STAGE,
7 RoboGuice. newDefaultRoboModule( this), new TimeModule());
8 }
9 }
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); // 单件
10
11 binder.bind(ITimeRepository. class)
12 .to(TimeRepository. class);
13
14 }
15
16 }
3 return new AndroidTimeRead(rep);
4 }
除此以外还能够通过实现Provider<T> 接口实现。
2
3 @Inject
4 ITimeRepository rep;
5
6 @Override
7 public AndroidTimeRead get() {
8
9 return new AndroidTimeRead( rep );
10 }
11
12 }
3 // 顺序无关,在详细的Activity中 被创建
4 binder
5 .bind(ITimeService. class )
6 .to(AndroidTimeRead. class );
7 // .in(Singleton.class); // 单件
8
9 binder.bind(ITimeRepository. class )
10 .to(TimeRepository. class );
11
12 binder.bind(AndroidTimeRead. class )
13 .toProvider(AndroidTimeReadProvider. class );
14
15 }
引入注入框架须要的思考:
3、其它可选择的框架如 dagger
本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5061551.html,如需转载请自行联系原作者
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
iOS HTML5的JS交互
//webView与H5点击交互走的代理 -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSURL * url = [request URL]; NSString * urlStr = url.absoluteString; NSString * protocolPrefix = @"scheme";//和后台定义好的字符 [self H5Js:protocolPrefix url:urlStr]; return YES; } //数组分离参数开始进行关键字提取以及相关操作 -(void)H5Js:(NSString *)protocolPrefix url:(NSString *)urlStr { if ([[urlStr lowercaseString]hasPrefix:protocolPrefix]) { urlStr = ...
- 下一篇
《从零开始学Swift》学习笔记(Day 14)——字符串的插入、删除和替换
对应可变字符串可以插入、删除和替换,String提供了几个方法可以帮助实现这些操作。这些方法如下: splice(_:atIndex:)。在索引位置插入字符串。 insert(_:atIndex:)。在索引位置插入字符。 removeAtIndex(_:)。在索引位置删除字符。 removeRange(_:)。删除指定范围内的字符串。 replaceRange(_:,with: String)。使用字符串或字符替换指定范围内的字符串。 代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 varstr= "Swift" print( "原始字符串:\(str)" ) str.splice( "Objective-Cand" .characters,atIndex:str.startIndex) print( "插入字符串后:\(str)" ) str.insert( "." ,atIndex:str.endIndex) print( "插入.字符后:\(str)" ) str.removeAtI...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7设置SWAP分区,小内存服务器的救世主
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Hadoop3单机部署,实现最简伪集群
- Mario游戏-低调大师作品
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程