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 !