通俗易懂的dagger2-實戰篇

1111111_發表於2017-10-28

前言

本篇是以 dagger2mvp 中的應用開發為例。如果還有不理解dagger2的,可以先看一下我之前發的通俗易懂的dagger2-入門篇或者先了解一下依賴倒置原則,當然也可以直接開幹

專案結構

先看一下專案結構圖:

結構圖.png
結構圖.png

  • 包結構從上到下依次
  • application
    放置專案Application基類,可以在onCreate()初始化一些全域性例項。
  • contract
    mvp中擔任連結viewmodel
  • di
    • component
      主要用於關聯@Module標註的類和Activity及Fragment的子類。
    • module
      用於對外提供物件,一般可在@Module標註的類中新增自定義方法,方法標註@Provides,方法體中可用來做一些例項化操作等。
  • model
    mvp中的model,這裡我是用來放實體類網路請求
  • presenter
    mvp中的presenter,為了方便我在裡面進行了網路請求並回撥資料到view
  • ui
    • view
      mvp中的view,放置通用的回撥方法

實戰

一般寫dagger2我都是先寫好module,先看看包 di -> module 中的程式碼:

前期準備

@Module
public class NetworkModule {

    @Singleton
    @Provides
    public GankService provideGankService() {
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        //設定超時時間
        httpClientBuilder.connectTimeout(15 * 1000, TimeUnit.MILLISECONDS);
        httpClientBuilder.writeTimeout(15 * 1000, TimeUnit.MILLISECONDS);
        httpClientBuilder.readTimeout(15 * 1000, TimeUnit.MILLISECONDS);
        return new Retrofit
                .Builder()
                .client(httpClientBuilder.build())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(GankService.BASE_URL)
                .build()
                .create(GankService.class);
    }
}複製程式碼

比較簡單,返回一個GankService介面物件,注意三個註解:

  • @Module
    用於對外提供物件,一般可在@Module標註的類中新增自定義方法,方法標註@Provides,方法體中可用來做一些例項化操作等。
  • @Provides
    配合@Module一起使用,@Provides用於標記方法,表示可以通過這個方法獲取一個物件,一般用於自定義類中。
  • @Singleton
    dagger 2中的單例模式,@Module類中使用了,@Component中也要使用。

這裡的NetworkModule類我只是用作一個依賴,我們可以在 AppComponent去引用它,在這之前再看看AppModule的程式碼:

@Module
public class AppModule {

    private Application mApplication;

    public AppModule(Application application) {
        mApplication = application;
    }

    @Singleton
    @Provides
    public Application provideApplication() {
        return mApplication;
    }
}複製程式碼

這裡沒有多大用處,只是在為了後期能在全域性呼叫Application基類物件,最後看看AppComponent的程式碼:

@Singleton
@Component(modules = {AppModule.class, NetworkModule.class})
public interface AppComponent {

    Application getApplition();

    GankService getGankService();
}複製程式碼
  • @Component
    主要用於關聯@Module標註的類和Activity及Fragment的子類。

在Application基類App中呼叫

public class App extends Application {

    private AppComponent mAppComponent;

    private static App sApp;

    @Override
    public void onCreate() {
        super.onCreate();
        sApp = this;
        mAppComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this))
                .networkModule(new NetworkModule())
                .build();
    }

    public static App getApp() {
        return sApp;
    }

    public AppComponent getAppComponent() {
        return mAppComponent;
    }

}複製程式碼

在這之前記得先在as選單欄中Build -> Rebuild Project,最後不要忘了在AndroidMainifest.xml application節點下加上基類android:name=".application.App"

如何在Activity or Fragment中呼叫呢

我寫了一個gank.io測試用例,前面我直接貼程式碼:

contract -> GankContract

public interface GankContract {

    interface View extends BaseView {

        void loadGankList(List<GankEntity> list);
    }

    interface Presenter {

        void getGank(String type, int count, int page);
    }

}複製程式碼

di -> GankModule

@Module
public class GankModule {

    private GankContract.View mView;

    public GankModule(GankContract.View view) {
        mView = view;
    }

    @ActivityScope
    @Provides
    public GankContract.View provideView() {
        return mView;
    }
}複製程式碼

@ActivityScope是我自定義的一個註解類

@Scope
public @interface ActivityScope {

}複製程式碼
  • @Scope
    Scopes可是非常的有用,Dagger2可以通過自定義註解限定註解作用域。

註解類在kotlin中的寫法:

@Scope
annotation class ActivityScope複製程式碼

di -> component

@Component(modules = {GankModule.class}, dependencies = {AppComponent.class})
public interface GankComponent {

    void inject(MainActivity mainActivity);
}複製程式碼

dagger2具體程式碼就這麼多了,應該算比較好理解的???

下面就是具體使用的程式碼了

MainActivity.class

public class MainActivity extends AppCompatActivity implements GankContract.View {

    private static final String TAG = "MainActivity";

    @Inject
    GankPresenter mPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        DaggerGankComponent.builder()
                .appComponent(App.getApp().getAppComponent())
                .gankModule(new GankModule(this))
                .build()
                .inject(this);

        mPresenter.getGank("Android", 10, 1);
    }

    @Override
    public void loadGankList(List<GankEntity> list) {
        for (GankEntity entity : list) {
            Log.d(TAG, "loadGankList: " + entity.toString());
        }
    }
}複製程式碼

presenter -> GankPresenter

public class GankPresenter implements GankContract.Presenter {

    private GankContract.View mView;
    private GankService mGankService;

    @Inject
    public GankPresenter(GankContract.View view, GankService gankService) {
        mView = view;
        mGankService = gankService;
    }

    @Override
    public void getGank(String type, int count, int page) {
        mGankService.getGankList(type, count, page)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<HttpResult<GankEntity>>() {
                    @Override
                    public void accept(HttpResult<GankEntity> gankEntityHttpResult) throws Exception {
                        mView.loadGankList(gankEntityHttpResult.getResults());
                    }
                });
    }

}複製程式碼

主要程式碼就這麼多了,如果還有什麼問題的話可以在下方留言,謝謝


在我的部落格中檢視更多簡單實用文章
不說了,RNG vs SKT 要開始了,首先恭喜RNG一波,溜了溜了

相關文章