继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

框架 Dagger2 的简单使用

红颜莎娜
关注TA
已关注
手记 125
粉丝 17
获赞 65

Dagger2

Google开发的针对Android的依赖注入框架,它的设计基于面向对象的一种设计模式(控制反转IOC),最大的特点就是低耦合。 
一般依赖注入框架都是通过反射实现,而Dagger2使用编译时生成代码,也就是apt动态生成。这样提高了效率不影响性能。

导入依赖

在Module的build.gradle下添加如下代码:

apply plugin: 'com.neenbedankt.android-apt'...dependencies {    ...
    apt 'com.google.dagger:dagger-compiler:2.4'
    compile 'com.google.dagger:dagger:2.4'
    compile 'org.glassfish:javax.annotation:10.0-b28'}

在Project的build.gradle下添加如下代码:

dependencies {   ...
   classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'}

导入完成Sync一下就可以了。

进入正题

要使用之前要明白各个部分是干嘛的,一头雾水直接用会很不爽。其实看很多项目比如google dagger2-mvp,在Activity或者Fragment中想要实例化对象并不是new一个对象,而是仅仅使用@Inject注解,这个对象就可以直接使用了。而且这个对象想要实现单例并不需要在编写单例设计模式,考虑同步锁之类的代码,其中一系列的操作dagger帮你实现了。这种方式既简单,又解藕还能提高程序员的装x境界..

使用Dagger首先要创建两个部分Component,Module当然还有你自己的对象(比如Fragment)
Component:个人理解就是一个中介,它帮你联系你需要注入的对象(Module中提供的对象),和要将对象注入给谁(Fragment)。
Module:在这里它可以提供你要的对象。

可以配合下面的代码理解上面的意思:

Module,Component,Provides

1.创建FragmentComponent:

@Component(modules = FragmentModule.class)public interface FragmentComponent {    //它会从Module中查找NewsListFragment中需要的Acitivity实例。找到后交给NewsListFragment。
    void inject(NewsListFragment newsListFragment);
}

2.创建FragmentModule:

@Modulepublic class FragmentModule {
    private Fragment fragment;    public FragmentModule(Fragment fragment) {        this.fragment = fragment;
    }    //这里提供的Activity就可以在Fragment中使用了。
    @Provides
    Activity provideActivity() {        return fragment.getActivity();
    }
}

3.在NewsListFragment相应的位置初始化FragmentComponent:

public class NewsListFragment extends Fragment {

    @Inject
    Activity activity;    @Inject
    User user;//可以看到这个User在Module中并没有提供,那么就去它构造中看看。

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        //这里在创建完Module,Component后要make Project编译一下!
        FragmentComponent fragmentComponent = DaggerFragmentComponent.builder()
                .fragmentModule(new FragmentModule(this))
                .build();
        fragmentComponent.inject(this);        return super.onCreateView(inflater, container, savedInstanceState);
    }
}public class User {
    //如果Fragment中需要这个实例,而Module中还没有提供该实例化,那么就必须在该对象的构造上加上@Inject注解。
    @Inject
    public User() {}
}
总结-->
其中的注解:
    @Module:提供对象的module必须用它来标注。
    @Provides:用于标注提供的对象。(提供的方法名称随意)
    @Component:作为中介的一个标注。
    @Inject:可以理解为整个过程的起点,最终找的就是它标注下的实例,或者方法。

整个过程就是:
    Component将Fragment注入进来,
    它会先去Fragment的Module中查找带有@Provides注解的对象,如果找到了Fragment中带有@Inject注解的对象则成功注入,
    如果Module中没有找到,去该对象中寻找带有@Inject注解的构造,找到则成功注入,
    否则失败。

接下来介绍Dagger中的一些注解:

@Singleton

如果刚才Fragment中的User想要实现单例:
        要在FragmentModule中:@Modulepublic class FragmentModule {
    ...    @Provides
    @Singleton
    User provideUser() {        //这就提供了单例,但是仅限于Fragment生命周期内。
        return new User();              
    }
}

同时FragmentComponent上要添加注解:@Singleton@Component(modules = FragmentModule.class)public interface FragmentComponent {
    //它会从Module中查找NewsListFragment中需要的Acitivity实例。找到后交给NewsListFragment。
    void inject(NewsListFragment newsListFragment);
}

@Scope

    Dagger中的单例可以限制生命周期内单例(整个app生命周期内单例,和Activity或者Fragment生命周期内单例)
    所以如果控制整个app生命周期内单例和Activity生命周期内单例,都用@Singleton就造成冲突会出现问题。
    -->这时我们可以自定义scope(其实就是有限制的控制单例):
        其实@Singleton的实现就是Dagger自定义的scope
@Scope@Documented@Retention(RUNTIME)public @interface Singleton {}
(1)自定义Fragment生命周期内单例:
@Scope@Documented@Retention(RetentionPolicy.RUNTIME)public @interface PerFragment {}
将刚才的FragmentModule中的单例注解替换为@PerFragment即可,FragmentComponent上的注解也要替换掉。1234512345
(2)想要实现全局的单例:
(假如我们要在Fragment中获取全局单例对象People)public class People {    public People(){}               
}
a.创建全局单例的Scope:
@Scope@Documented@Retention(RetentionPolicy.RUNTIME)public @interface PerApp {}12341234
b.创建全局AppModule:
@Modulepublic class AppModule {
    private final Context context;    public AppModule(Context context) {        this.context = context;
    }    @Provides
    Context provideContext() {        return context;
    }    //这里提供的对象可以在依赖AppComponent的所有Component注入的对象中使用
    // 比如(ActivityComponent,FragmentComponent中inject的对象)
    // 自然这里限制的单例,全局有效。
    @Provides
    @PerApplication
    People proPeople() {        return new People();
    }
}
c.创建全局AppComponent:
@PerApplication@Component(modules = AppModule.class)public interface AppComponent {
    //它的特点是,需要向下层(也就是需要的层)提供AppModule中提供好的对象
    Context getContext();//方法名随意
    People getPeople();
}
注意:刚才的FragmentComponent要依赖全局的APPComponent:@PerFragment@Component(dependencies = AppComponent.class, modules = FragmentModule.class)public interface FragmentComponent {
    void inject(NewsListFragment newsListFragment);
}
d.在Application的onCreate()方法中初始化AppComponent:
@Overridepublic void onCreate() {    super.onCreate();
    appComponent = DaggerAppComponent.builder()
            .appModule(new AppModule(this))
            .build();
}
e.在Fragment中获取FragmentComponent:
public class NewsListFragment extends Fragment {

    @Inject
    Activity activity;    @Inject
    User user;    @Inject
    People people;//这个people就是全局单例。

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        FragmentComponent fragmentComponent = DaggerFragmentComponent.builder()
               .appComponent(appComponent//app中初始化好的)
               .fragmentModule(new FragmentModule(this))
               .build();
        fragmentComponent.inject(this);        return super.onCreateView(inflater, container, savedInstanceState);
    }
}
            总结:-->其实之前写这么多代码,都是配置,完事在相应的Fragment或Activity中使用就非常方便了

原文链接:http://www.apkbus.com/blog-866962-68151.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP