前言
本篇是以 dagger2 在 mvp 中的應用開發為例。如果還有不理解dagger2的,可以先看一下我之前發的通俗易懂的dagger2-入門篇或者先了解一下依賴倒置原則,當然也可以直接開幹
專案結構
先看一下專案結構圖:
- 包結構從上到下依次
- application
放置專案Application
基類,可以在onCreate()
初始化一些全域性例項。 - contract
mvp中擔任連結view
和model
- di
- component
主要用於關聯@Module標註的類和Activity及Fragment的子類。 - module
用於對外提供物件,一般可在@Module標註的類中新增自定義方法,方法標註@Provides,方法體中可用來做一些例項化操作等。
- component
- model
mvp中的model
,這裡我是用來放實體類和網路請求 - presenter
mvp中的presenter
,為了方便我在裡面進行了網路請求並回撥資料到view
- ui
- view
mvp中的view
,放置通用的回撥方法
- 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一波,溜了溜了