1,这一篇博客是和大家一起来封装我们最后的Dagger2,其实之前也写过关于简单的Dagger2,这里是地址,完全没了解的同学可以先去看一下这篇,感谢很多小伙伴一直在耐心的等待这一篇
2,Dagger2可以说是些技术中最难上手的,不过把主要的四个注解理解到位了,基本上就可以用了:
@Inject Inject主要有两个作用,一个是使用在构造函数上,通过标记构造函数让Dagger2来使用(Dagger2通过Inject标记可以在需要这个类实例的时候来找到这个构造函数并把相关实例new出来)从而提供依赖,另一个作用就是标记在需要依赖的变量让Dagger2为其提供依赖。 @Provide 用Provide来标注一个方法,该方法可以在需要提供依赖时被调用,从而把预先提供好的对象当做依赖给标注了@Injection的变量赋值。provide主要用于标注Module里的方法 @Module 用Module标注的类是专门用来提供依赖的。有的人可能有些疑惑,看了上面的@Inject,需要在构造函数上标记才能提供依赖,那么如果我们需要提供的类构造函数无法修改怎么办,比如一些jar包里的类,我们无法修改源码。这时候就需要使用Module了。Module可以给不能修改源码的类提供依赖,当然,能用Inject标注的通过Module也可以提供依赖 @Component Component一般用来标注接口,被标注了Component的接口在编译时会产生相应的类的实例来作为提供依赖方和需要依赖方之间的桥梁,把相关依赖注入到其中。
下面你这张图片很相像的概括了上面四个标签的作用
还有两个常见的标签是@Scope和@Qulifier ,@Scope标签你可以将它理解成单例标记,@Qulifier可以简单的理解成区分需要的对象有两个或者两个以上构造方法(主要用于区分),
首先我们用一个简单的场景来引入吧,现在我们项目使用MVP架构, 而引入Dagger2的主要目的是解决我们在Activity中new Presenter对象,先看一下我们在引用之前代码是怎么样的吧
package com.qianmo.myview2; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.qianmo.myview2.presenter.HiPresenterImpl; public class MainActivity extends AppCompatActivity { private HiPresenterImpl hiPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //直接new对象 hiPresenter = new HiPresenterImpl(); } }
这时候引用Dagger2,再看看我们的代码
MainActiivty.java
package com.qianmo.myview2; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.qianmo.myview2.presenter.HiPresenterImpl; import javax.inject.Inject; public class MainActivity extends AppCompatActivity { @Inject private HiPresenterImpl hiPresenter; //这里改变了 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
Presenter.java
package com.qianmo.myview2.presenter; import com.qianmo.myview2.contract.HiContract; import javax.inject.Inject; /** * Created by MVPHelper on 2016/10/20 */ public class HiPresenterImpl implements HiContract.Presenter{ @Inject public HiPresenterImpl(){ } }
光上面的这两个标注还不够,我们还要创建对应的Module和Component
MainModule.java
package com.qianmo.myview2.di.module; import com.qianmo.myview2.presenter.HiPresenterImpl; import dagger.Module; import dagger.Provides; /** * Created by wangjitao on 2017/3/9 0009. * E-Mail:543441727@qq.com */ @Module public class MainModule { @Provides HiPresenterImpl provideHiPresenterImpl() { return new HiPresenterImpl(); } }
MainComponent.java
package com.qianmo.myview2; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.qianmo.myview2.di.component.DaggerMainComponent; import com.qianmo.myview2.di.module.MainModule; import com.qianmo.myview2.presenter.HiPresenterImpl; import javax.inject.Inject; public class MainActivity extends AppCompatActivity { @Inject private HiPresenterImpl hiPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerMainComponent.builder().mainModule(new MainModule()).build().inject(this); hiPresenter.say(); } }
这样我们就简单的使用了,再来简单的分析一下流程 :被 @Inject 注解的代码存在某种联系,当代码执行到 @Inject 的时候程序会自动进入到这个类的构造方法中,如果正巧这个构造方法也被 @Inject 修饰了,那么系统就会帮我们自动创建对象。
3,封装
由上面的项目我们进行过度,但我们封装的时候,主要是要在activity和fragment来持有Presenter对象,先来封装Activity,这是目录
先看一下我们之前的presenter的创建,在BaseActivity中添加抽象方法,在Mainactivity中重写方法再new对象
先创建Application的Module,Application的话主要是提供上下文环境,而appliacation中的component,只是提供Context展示方法get方法
AppModule.java
package com.qianmo.mvpproject.di.module; import com.qianmo.mvpproject.App; import com.qianmo.mvpproject.di.ContextLife; import javax.inject.Singleton; import dagger.Module; import dagger.Provides; /** * Created by wwangjitao on 16/8/7. */ @Module public class AppModule { private final App application; public AppModule(App application) { this.application = application; } @Provides @Singleton @ContextLife("Application") App provideApplicationContext() { return application; } }
AppComponent.java
package com.qianmo.mvpproject.di.component; import com.qianmo.mvpproject.App; import javax.inject.Singleton; import com.qianmo.mvpproject.di.ContextLife; import com.qianmo.mvpproject.di.module.AppModule; import dagger.Component; /** * Created by wangjitao on 16/8/7. */ @Singleton @Component(modules = AppModule.class) public interface AppComponent { @ContextLife("Application") App getContext(); // 提供App的Context }
而Activity的Module主要是提供Activity和上下文Context对象,对应的Activity的component主要是将提供的对象注入到需要它的地方
ActivityModule.java
package com.qianmo.mvpproject.di.module; import android.app.Activity; import android.content.Context; import com.qianmo.mvpproject.base.BaseRxPresenter; import com.qianmo.mvpproject.di.ActivityScope; import dagger.Module; import dagger.Provides; /** * Created by codeest on 16/8/7. */ @Module public class ActivityModule { private Activity mActivity; public ActivityModule(Activity activity) { this.mActivity = activity; } @Provides @ActivityScope public Activity provideActivity() { return mActivity; } @Provides public Context provideContext() { return mActivity; } }
ActivityComponent.java
package com.qianmo.mvpproject.di.component; import android.app.Activity; import com.qianmo.mvpproject.di.ActivityScope; import com.qianmo.mvpproject.di.module.ActivityModule; import com.qianmo.mvpproject.ui.activity.CheckVersionActivity; import dagger.Component; /** * Created by codeest on 16/8/7. */ @ActivityScope @Component(dependencies = AppComponent.class, modules = ActivityModule.class) public interface ActivityComponent { Activity getActivity(); void inject(CheckVersionActivity welcomeActivity); }
再在BaseActivity中去调用
BaseActivity.java
package com.qianmo.mvpproject.base; import android.app.Activity; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import javax.inject.Inject; import com.qianmo.mvpproject.App; import com.qianmo.mvpproject.R; import com.qianmo.mvpproject.di.component.ActivityComponent; import com.qianmo.mvpproject.di.component.DaggerActivityComponent; import com.qianmo.mvpproject.di.module.ActivityModule; import butterknife.ButterKnife; import butterknife.Unbinder; /** * Created by wangjitao on 2016/11/8 0008. * 基类Activity的封装 * 一般使用mvp模式的话会在BaseActivity中进行P和V的初始化绑定 */ public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity implements BaseView { //这里添加了注入 @Inject protected T mPresenter; .......省略 protected void onCreate(@Nullable Bundle savedInstanceState) { .......省略 super.onCreate(savedInstanceState); setContentView(getLayout()); //这里添加了注入的调用 initInject(); if (mPresenter != null) mPresenter.attachView(this); } //添加调用方法 protected ActivityComponent getActivityComponent(){ return DaggerActivityComponent.builder() .appComponent(App.getAppComponent()) .activityModule(getActivityModule()) .build(); } protected ActivityModule getActivityModule(){ return new ActivityModule(this); } }
ok,这样我们就封装了,同理Fragment,这里就不废话写了,下面把github地址贴上,后面打算这些东西写一个展示类的app,又要到处找接口了,See You Next Time !