Android 依赖注入: Dagger 2 实例讲解(一)

本文原创,转载请注明出处:http://blog.csdn.net/zjbpku

关于Dagger,在之前的博文(Android 依赖注入:Dagger 实例讲解(Demo下载))中已有介绍, 本文说的Dagger 2主要是由Google技术

人员参与开发的,当然包括Square的各位及其他一些Contributors在内的大牛也贡献了不少。该项目大概是从去年11月份开始启动的,到目前该项

目还在继续进行,Snapshot version也是刚刚发布不久,从Github提供的内容看,不久会是Pre Release Version,然后才是Release Version,由于

现在还是预览版,还不稳定,请谨慎使用,到Pre Release时才会相对比较稳定,可以使用来进行项目开发。本人关注这个项目依旧,就提前通过一

个Demo来简单介绍一下Dagger 2.

Dagger 2是Dagger 1.x的增强版,在Dagger 1.x中,@Inject和@Provides annotation 构成了对象的图谱(graph),依靠之间的依赖

关系而链接在一起。通过定义好的图谱集(ObjectGraph)可以方便的调用代码。而在Dagger 2中,这种关系被带有无参方法的接口代替,

这种方法返回的类型就是所需类型。这种接口的实现是通过@Component 注解且传入modules参数来定义的。如:

@Component(
//        dependencies = ApplicationComponent.class,
        modules = ActivityModule.class
)
public interface ActivityComponent {
    MainActivity injectActivity(MainActivity activity);

    ToastHelper getToastHelper();
}

在编译时,Dagger 2会自动生成以Dagger_为前缀的此接口的实现Dagger_AcitvityComponent.通过调用此的builder()方法来获得一个

实例,通过该方法返回的builder来设置其他依赖,通过build来获得一个新的实例。

 this.component = Dagger_ActivityComponent.builder()
//                .applicationComponent(((DaggerApplication) getApplication()).getComponent())
                .activityModule(new ActivityModule(this))
                .build();

另外一点,如果@Component注解的接口中的方法没有参数,生成的实例中会生成一个create()方法,此create()方法实际上就是

builder().build();此点在以后的代码中会提到。

下面介绍Demo:

Demo使用最新的AndroidStudio (以下简称AS)1.0.2版本,既然使用AS,就少不了gradle.build文件的配置,此项目gradle配置如下:

apply plugin: 'com.android.application'
apply plugin: 'android-apt'
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.0.0'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4' // 3
    }
}

allprojects {
    repositories {
        mavenCentral()
        maven {
            url 'https://oss.sonatype.org/content/repositories/snapshots/'
        }
    }
}
android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "com.example.zjbpku.dagger2"
        minSdkVersion 19
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

def Dagger2_Version = '2.0-SNAPSHOT'

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
    // 1. Dagger 2.0
    compile "com.google.dagger:dagger:$Dagger2_Version"
    apt "com.google.dagger:dagger-compiler:$Dagger2_Version"
    // 2.
    compile 'org.glassfish:javax.annotation:10.0-b28'
}

分别看一下gradle.build文件中注释1,2,3。

注释1:是配置依赖Dagger 2,版本是2.0-SNAPSHOT,这里相比之前版本的Dagger就是从com.square.dagger 变为现在的com.google.dagger,

当然这不是重点。

注释2:为什么要加上这一句呢?因为Dagger 2 中会用到@Generated注解(后面讲),而javax.anotation.generated在java 6及以上的版本中都有,

在Android API 中是没有的,所以在Android项目中一定要加此句,如果不加就有提示以下错误:

error: cannot find symbol class Generated
error: package javax.annotation does not exist

注释3:就不多少了,具体作用请看http://blog.csdn.net/zjbpku/article/details/22976291,另不要忘记加

apply plugin:android-apt

在之前的Dagger中@module是一个关键注解,在Dagger 2中同样少不了,此Demo中用到的两个Module如下:(用过Dagger的不会觉得有问题)

ActivityModule.java:

/**
 * Created by zjbpku on 12/20/14.
 */

@Module
public class ActivityModule {

    private Activity mActivity;

    public ActivityModule(Activity activity) {
        mActivity = activity;
    }

    @Provides
    Activity providesActivity() {
        return mActivity;
    }

}

ApplicationModule.java:

/**
 * Created by zjbpku on 12/20/14.
 */
@Module
public class ApplicationModule {
    Application mApplication;

    ApplicationModule(Application application) {
        mApplication = application;
    }

    @Provides
    Application providesApplication() {
        return mApplication;
    }
}

写好之后,添加两个@Component注解的接口,此Demo非常简单,只是来尝试使用一下Dagger 2,Application相关的其实可以不用,对Demo不会

有什么影响,但在实际项目中还是必须添加的,所以这里也给加上。

Activityomponent.java:

/**
 * Created by zjbpku on 12/20/14.
 */

@Component(
        dependencies = ApplicationComponent.class,
        modules = ActivityModule.class
)
public interface ActivityComponent {
    MainActivity injectActivity(MainActivity activity);

    ToastHelper getToastHelper();
}

ApplicationComponent.java:

/**
 * Created by zjbpku on 12/20/14.
 */
@Component(
        modules = ApplicationModule.class
)
public interface ApplicationComponent {
    DaggerApplication injectApplication(DaggerApplication application);
}

DaggerApplication.java:

/**
 * Created by zjbpku on 12/20/14.
 */
public class DaggerApplication extends Application {

    private ApplicationComponent component;

    @Override
    public void onCreate() {
        super.onCreate();
        this.component = Dagger_ApplicationComponent.builder().applicationModule(new ApplicationModule(this)).build();
        this.component.injectApplication(this);
    }

    ApplicationComponent getComponent() {
        return this.component;
    }
}

//添加只是为了测试

ToastHelper.java:

/**
 * Created by zjbpku on 12/22/14.
 */
public class ToastHelper {

    @Inject
    ToastHelper() {
    }

    //@Inject
    //Utils utils;
    Toast toast = null;

    public void showToast(Context context, CharSequence text) {
        if (toast == null) {
            toast = Toast.makeText(context, text, Toast.LENGTH_LONG);
        } else {
            toast.setText(text);
        }
        toast.show();
    }

    public void show(Context context) {
       // showToast(context, utils.getContent());
    }
}

MainActivity.java:

package com.example.zjbpku.dagger2;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

    private ActivityComponent component;
//    @Inject
//    ToastHelper toastHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.component = Dagger_ActivityComponent.builder()
                .applicationComponent(((DaggerApplication) getApplication()).getComponent())
                .activityModule(new ActivityModule(this))
                .build();
        this.component.injectActivity(this);
        setContentView(R.layout.activity_main);
    }

    public void helloDagger2(View v) {
//        toastHelper.showToast(this, "Dagger 2");
//        toastHelper.show(this);
        this.component.getToastHelper().showToast(this, "Dagger 2 Demo");
    }

}

可以看到,Dagger 2 消除了Dagger 1.x 中所有的映射(reflection),通过添加@Component,移除ObjectGraph/Injector使代码更加的清晰了。

到此,Dagger 2的基本用法已经结束,在ActivityComponet接口中你发现有getToastHelper()方法,在Mainctivity中发现@Inject注解的ToastHelper

是注销的,且在helloDagger2(View v)方法中也是注销的,这是因为,开始时getToastHelper()方法是没有的,是直接在Mainctivity中通过@Inject直接注入

的,后来阅读Dagger 2的相关资料发现,其实这并不是Dagger 2的所期望的,Dagger 2希望使用@Component注解接口将依赖关系链接起来,所以才改用

现在这种方法。其实两种都能达到一样的效果,只是Dagger自动生成的代码有所差异,这个之后会进一步介绍。

时间: 2024-10-12 07:53:20

Android 依赖注入: Dagger 2 实例讲解(一)的相关文章

Android依赖注入Dagger的使用和源码解析(上篇)

一.基本概念 依赖注入(DI)和控制反转(IOC): 依赖注入是从应用程序的角度在描述,可以把依赖注入描述完整点:应用程序依赖容器创建并注入它所需要的外部资源:而控制反转是从容器的角度在描述,描述完整点:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源. 使用依赖注入可以带来以下好处: 依赖的注入和配置独立于组件之外. 因为对象是在一个独立.不耦合的地方初始化,所以当注入抽象方法的时候,我们只需要修改对象的实现方法,而不用大改代码库. 依赖可以注入到一个组件中:我们可以注入这

关于Android依赖注入框架ButterKnife和Dagger的简单比较

最近调研了Android平台可以使用的依赖注入框架.发现现在常用的有四种.Dagger.Butter Knife.RoboGuice.Android Annotations.经过一系列的比较,最后我们的选择 的范围缩小到Dagger.Butter Knife这2个框架上.其实在国内外使用的比较多的应该是Dagger.但是我觉得还是有点复杂了,再看jakewharton的blog时,他也提到了dagger,我 摘抄了他在stackoverflow上回答Difference between Dagg

Android 依赖注入框架RoboGuice

概述 在开发应用时一个基本原则是模块化,并且尽最大可能性地降低模块之间的耦合性.Dependency injection 大大降低了类之间的依赖性,可以通过annotation描述类之间的依赖性,避免了直接调用类似的构造函数或是使用Factory来参加所需的类,从而降低类或模块之间的耦合性,以提高代码重用并增强代码的可维护性. Google Guice提供了Java平台上一个轻量级的 Dependency injection 框架,并可以支持开发Android应用.本指南将使用Android平台

研究 Spring MVC 将请求分发到 Spring 依赖注入的类实例

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 一上午时间,碰了 N 个钉子,不断地把钉子拨掉,记录一下选择的工具和方法: 1.首先 Spring Mvc 框架的下载,那么有三个包是必不可少的:

Android 依赖注入函数库Roboguice(一)

Roboguice是一个用于Android应用的依赖注入框架,使用Google官方的Guice库位极大地简化了Android的依赖注入.使用他使编程变得更加简单有趣. 使用Roboguice需要几个jar点击下载 下载知道导入到自己的项目中 使用Roboguice是Activity页面需要继承RoboActivity /** * */ package com.example.roboguicetest; import com.google.inject.Inject; import robogu

Android 依赖注入 ButterKnife 基本使用

ButterKnife 是一个快速 Android View 注入框架,开发者是Jake Wharton,简单的来说,ButterKnife 是用注解的方式替代findViewById和setXXXListener 项目GitHub地址:https://github.com/JakeWharton/butterknife/ Android Studio 配置步骤可以直接参考Github上的介绍,很简单. ButterKnife 是在编译时注解,不会在运行时产生负担,Build工程后你会发现它生成

Android 依赖注入

Dagger2 ![https://github.com/google/dagger](github托管地址) 1. 安装依赖: ``` compile 'com.google.dagger:dagger:2.0.1' compile 'com.google.dagger:dagger-compiler:2.0.1' ``` 2. 新建一个Component,这是一个接口: ``` @Component(modules = ApplicationModule.class) public inte

Android依赖注入之BufferKnife 8.0注解使用

前言: App项目开发大部分时候还是以UI页面为主,这时我们需要调用大量的findViewById以及setOnClickListener等代码,控件的少的时候我们还能接受,控件多起来有时候就会有一种想砸键盘的冲动.所以这个时候我们想着可以借助注解的方式让我们从这种繁重的工作中脱离出来,也让代码变得更加简洁,便于维护,今天主要学习一下只专注View.Resource.Action注解框架BufferKnife . BufferKnife 介绍 BufferKnife 是一个专注于Android系

【FastDev4Android框架开发】RecyclerView完全解析之结合AA(Android Annotations)注入框架实例(三十)

(一).前言: 话说RecyclerView已经面市很久,也在很多应用中得到广泛的使用,在整个开发者圈子里面也拥有很不错的口碑,那说明RecyclerView拥有比ListView,GridView之类控件有很多的优点,例如:数据绑定,Item View创建,View的回收以及重用等机制.本系列文章会包括到以下三个部分: RecyclerView控件的基本使用,包括基础,进阶,高级部分,动画之类(点击进入) RecyclerView控件的实战实例(点击进入) RecyclerView控件集合AA