【Android 进阶】Dagger2 系列:入门案例一

介绍

A fast dependency injector for Android and Java
一个在 Android 和 Java 平台上使用的快速的依赖注入框架。 
类似 java 开发中的 spring 框架,但使用难度比 spring 大一点点。 
依赖注入框架主要用于模块间解耦,提高代码的健壮性和可维护性。

几个必须知道的概念:

什么是依赖:

如果在 Class A 中,有 Class B 的实例,则称 Class A 对 Class B 有一个依赖。

什么是依赖注入:

依赖注入就是非自己主动初始化依赖,而通过外部来传入依赖的方式,简单来说就是不使用 new 来创建依赖对象。

三大元素:

必不可少的元素有三种,Module,Component,Container

 
- Container 拥有者,容器等意思,其中 Activity 就是 Dagger2 中的 Container. 
- Component Acitvity 和 依赖对象之间的一个桥梁。 
- Module 就是负责提供对象的。

用到的注解如下:

@Inject: 
通常在需要依赖的地方使用这个注解。换句话说,你用它告诉 Dagger 这个类或者字段需要依赖注入。这样,Dagger 就会构造一个这个类的实例并满足他们的依赖。

@Module: 
Modules 类里面的方法专门提供依赖,所以我们定义一个类,用 @Module 注解,这样 Dagger 在构造类的实例 
时候,就知道从哪里去找到需要的 依赖。modules 的一个重要特征是它们设计为分区并组合在一起(比如说, 
我们的 app 中可以有多个组成在一起 的modules)

@Provide: 
在 modules 中,我们定义的方法是用这个注解,以此来告诉 Dagger 我们想要构造对象并提供这些依赖。

@Component: 
Components 从根本上来说就是一个注入器,也可以说是 @Inject 和 @Module 的桥梁,它的主要作用就是连接这两个部分。 Components 可以提供所有定义了的类型的实例,比如:我们必须用 @Component 注解一个接口然后列出所有的

官方 Github 地址以及 API 说明文档::

google/dagger

说明文档

使用准备:

project 的 build.gradle 添加

dependencies {
     ... // 其他 classpath
     classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8‘ //添加 apt 命令
 }

module 的 build.gradle 添加

// 添加其他插件
apply plugin: ‘com.neenbedankt.android-apt‘//添加 apt 命令

dependencies {
    apt ‘com.google.dagger:dagger-compiler:2.0.2‘ //指定注解处理器
    compile ‘com.google.dagger:dagger:2.0.2‘  //dagger 公用 api
    provided ‘org.glassfish:javax.annotation:10.0-b28‘  //添加 android 缺失的部分 javax 注解
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

直接从代码出发吧

代码完整,可以直接粘贴到自己 AS 验证。

看一个简单的例子:

代码如下:

MainActivity.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:直接依赖注入 ApiService 对象
 */
public class MainActivity extends AppCompatActivity {
    @Inject
    ApiService mApiService;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //rebuild一下,自动生成 DaggerUserComponet 类
        DaggerUserComponet.create().inject(this);
        mApiService.register();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

ApiService.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:
 */
public class ApiService {

    public void register(){
        Log.e("ApiService","register");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

UserModule.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:提供实例的 Module
 */
@Module
public class UserModule {
    @Provides
    public ApiService provideApiService(){
        Log.e("UserModule","provideUserManger");
        return new ApiService();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

UserComponet

/**
 * Created by Veyron on 2017/5/9.
 * Function:Activity 和 Module 之间的桥梁
 * @Component(modules = {UserModule.class}) 表示和 Module 对接
 *
 * void inject(MainActivity activity);表示在 MainActivity 中注入
 */
@Component(modules = {UserModule.class})
public interface UserComponet {

     void inject(MainActivity activity);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

输出:

E/UserModule: provideApiService
E/ApiService: register
  • 1
  • 2
  • 1
  • 2

更复杂一点的例子:

MainActivity.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:直接依赖注入 UserManger 对象
 */
public class MainActivity extends AppCompatActivity {
  /*  @Inject
    ApiService mApiService;*/
    @Inject
    UserManger mUserManger;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        DaggerUserComponet.builder()
                .userModule(new UserModule()).build().inject(this);
        //DaggerUserComponet.create().inject(this); 等价上面

        mUserManger.register();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

ApiService.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:直接依赖注入 UserManger 对象
 */
public class ApiService {

    //当module里面没有提供本类的对象,默认调用下面这个 @Inject 注释的构造函数(只能声明一个)
    @Inject
    public ApiService(){
        Log.e("ApiService","ApiService的构造函数");
    }

  /*  @Inject
    public ApiService(String url){
        Log.e("ApiService","url---");
    }*/

    public void register(){
        Log.e("ApiService","register");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

UserModule.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:
 */
@Module
public class UserModule {
    @Provides
    public ApiService provideApiService(){
        Log.e("UserModule","provideApiService-");
        return new ApiService();
    }

    @Provides
    public String url(){
        return "url";
    }
    // 将会调用这个 public ApiService(String url) 方法

    //单独调用本方法的话,apiService 的对象是上面提供的,另一种使用 apiservice 的构造方法
    @Provides
    public UserManger provideUserManger(ApiService apiService){
        Log.e("UserModule","provideUserManger");
        return new UserManger(apiService);
    }
}

  • 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
  • 26
  • 27
  • 28
  • 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
  • 26
  • 27
  • 28

UserComponet.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:Activity 和 Module 之间的桥梁
 * @Component(modules = {UserModule.class}) 表示和 Module 对接
 *
 * void inject(MainActivity activity);表示在 MainActivity 中注入
 */
@Component(modules = {UserModule.class})
public interface UserComponet {

     void inject(MainActivity activity);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

输出如下:

E/UserModule: provideApiService
E/ApiService: ApiService 的构造函数
E/UserModule: provideUserManger
E/UserManger: register
E/ApiService: register
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

更复杂点

第二个例子其中,将 UserModule.java,UserModule.java 改动如下:

UserModule.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:
 */
@Module
public class UserModule {
    /*@Provides
    public ApiService provideApiService(){
        Log.e("UserModule","provideApiService");
        return new ApiService();
    }*/

    @Provides
    public String url(){
        return "传给 ApiService 构造函数的参数";
    }
    // 将会调用这个 public ApiService(String url) 方法

    //单独调用本方法的话,apiService 的对象是上面提供的,另一种使用 apiservice 的构造方法
    @Provides
    public UserManger provideUserManger(ApiService apiService){
        Log.e("UserModule","provideUserManger");
        return new UserManger(apiService);
    }
}
  • 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
  • 26
  • 27
  • 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
  • 26
  • 27

ApiService.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:@Inject 声明的构造函数只能有一个
 */
public class ApiService {

    //当module里面没有提供本类的对象,默认调用下面这个 @Inject 注释的构造函数(只能声明一个)
    /*@Inject
    public ApiService(){
        Log.e("ApiService","ApiService的构造函数");
    }*/

    @Inject
    public ApiService(String url){
        Log.e("ApiService","url="+url);
    }

    public void register(){
        Log.e("ApiService","register");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

输出是:

E/ApiService: url=传给ApiService构造函数的参数
E/UserModule: provideUserManger
E/UserManger: register
E/ApiService: register
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

看了输出,再参考下代码,其实就知道是怎么回事了。 
可以得到一点结论就是:在 UserModule 中需要 ApiService 对象,但是 UserModule 中并没提供,那么就去查看 ApiService 中有没有 @Inject 声明的构造函数,如果有且是无参构造函数,那么 UserModule 中就相当拿到了 ApiService 对象。如果是有参的构造函数,则 UserModule 中必须有提供该参数的实例,如本例子中的 public String url() 函数,返回的 String 就是给构造函数当参数的,那么 UserModule 中就等于有了 ApiService 对象。

声明

建议把上面的例子都运行一遍,就会有体会 Dagger2 的使用是怎样的。 
篇幅有限,Dagger2 使用方式也有很多, 下一篇接着介绍 其他例子。

http://blog.renren.com/blog/937184755/994083793
http://blog.renren.com/blog/937184755/994083886
http://blog.renren.com/blog/937184755/994084167
http://gamebbs.51.com/thread-324928-1-1.html
http://blog.163.com/m13094739605_1/blog/static/27240604620174100133493/
http://blog.163.com/m13094739605_1/blog/static/2724060462017410028912/
http://blog.163.com/m13094739605_1/blog/static/27240604620174100237428/
http://blog.163.com/m13094739605_1/blog/static/27240604620174100315903/
http://www.230la.com/com/wz801234567/news/itemid-3253535.html

时间: 2024-08-07 13:06:02

【Android 进阶】Dagger2 系列:入门案例一的相关文章

Android进阶——多线程系列之Thread、Runnable、Callable、Future、FutureTask

多线程系列之Thread.Runnable.Callable.Future.FutureTask 前言 多线程一直是初学者最抵触的东西,如果你想进阶的话,那必须闯过这道难关,特别是多线程中Thread.Runnable.Callable.Future.FutureTask这几个类往往是初学者容易搞混的.这里先总结这几个类特点和区别,让大家带着模糊印象来学习这篇文章 Thread.Runnable.Callable:都是线程 Thread特点:提供了线程等待.线程睡眠.线程礼让等操作 Runnab

【Android进阶系列教程】前言

起因 因为初学Android的时候还没有写博客的意识,现在Android的门是入了,正在进阶的道路上行走,但是就这一路也走了不少的弯路.我想,总得来说Android入门还是比较容易的,网络资源比较丰富,就连Google官方都提供了eclipse+SDK+ADT的集成(当年是要自己装ADT插件配置的),下载下来解压->打开eclipse->直接就helloworld了.然后自己按照书上搞几个Activity互相跳转,监听几个按钮也能做出各种有意思的玩意儿. 现在想起来,入门真的没啥特别大的难度.

Android视频录制从不入门到入门系列教程(三)————视频方向

运行Android视频录制从不入门到入门系列教程(二)————显示视频图像中的Demo后,我们应该能发现视频的方向是错误的. 由于Android中,Camera给我们的视频图片的原始方向是下图这个样子的: 就是说,即使你是竖着拿手机的,Camera提供给你的视频图像的方向还是上图那样横着的图片. 我们可以通过下述方向改变Camera提供的视频图像的方法: camera.setDisplayOrientation(90); 让图像顺时针旋转90度,视频图像的方向就正常的. 本篇文章DEMO下载.

Android自定义组件系列【6】——进阶实践(3)

上一篇<Android自定义组件系列[5]--进阶实践(2)>继续对任老师的<可下拉的PinnedHeaderExpandableListView的实现>进行了分析,这一篇计划中间插一段"知识点",对Android中的事件分发机制进行解析.细心的朋友可能会发现,打开大牛写的Android项目,里面很多组件都是自定义的(这就是为什么界面和体验这么吸引你的原因),但是要灵活的去自定义组件就必须对手势(也就是各种监听)必须熟悉,能处理好事件之间的关系. 先看一段代码:

Android自定义组件系列【7】——进阶实践(4)

上一篇<>中补充了关于Android中事件分发的过程知识,这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpandableListView的实现>. 一.StickyLayout中的OnGiveUpTouchEventListener接口的作用是什么? public interface OnGiveUpTouchEventListener { public boolean giveUpTouchEvent(MotionEvent event); } 在Sticky

Android进阶(二十八)上下文菜单ContextMenu使用案例

上下文菜单ContextMenu使用案例 前言 回顾之前的应用程序,发现之前创建的选项菜单无法显示了.按照正常逻辑来说,左图中在"商品信息"一栏中应该存在选项菜单,用户可进行分享等操作,但是现在此操作莫名其妙的消失了.写了个测试Demo,如中图所示,一切按照逻辑显示正常.怪就怪在项目中无法显示,起初设想是因为Android系统版本太高问题,但是在别的手机上测试之后发现问题依旧存在.难道是因为顶部Tab标题栏遮挡住了选项菜单的显示?继续测试,通过在别的没有Tab标题栏的页面测试选项菜单,

Android自定义组件系列【5】——进阶实践(1)

简介 项目开发中发现问题.解决问题这个过程中会出现很多问题,比如重复出现.某个问题的遗留,这些问题的本质就是设计模式.今天记录设计模式的知识点. 内容 在java以及其他的面向对象设计模式中,类与类之间主要有6种关系,他们分别是:依赖.关联.聚合.组合.继承.实现.它们的耦合度依次增强. 依赖关系:对于两个相对独立的对象,当一个对象负责构造另一个对象的实例,或者依赖另一个对象的服务时,这两个对象之间主要体现为依赖关系.关联关系:分为单向关联和双向关联.在java中,单向关联表现为:类A当中使用了

Android自定义组件系列【5】——进阶实践(2)

上一篇<Android自定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这一篇我们来看看ExpandableListView的使用并实现剩下的部分. 原文出处:http://blog.csdn.net/singwhatiwanna/article/details/25546871 一.ExpandableListView的用法 ExpandableListView是ListView的

Spring Boot从入门到进阶教程系列 -- 集成Freemarker配置

步骤1. 我们可先配置application.properties的Freemarker基本配置,可参考第一篇教程[Spring Boot从入门到进阶教程系列 -- 外部Tomcat多方式启动,加密解密配置数据] 核心配置 ######################################################## ### freemarker ######################################################## spring.fr

我的Android进阶之旅------&gt;经典的大牛博客推荐(排名不分先后)!!

本文来自:http://blog.csdn.net/ouyang_peng/article/details/11358405 今天看到一篇文章,收藏了很多大牛的博客,在这里分享一下 谦虚的天下 柳志超博客 Android中文Wiki AndroidStudio-NDK开发-移动开发团队谦虚的天下 - 博客园gundumw100博客 - android进阶分类文章列表 - ITeye技术网站CSDN博文精选:Android系列开发博客资源汇总 - CSDN.NET - CSDN资讯Android笔