dagger2的优势,省去无谓的体力劳动,增加开发效率,代码解耦
rxjava的优势,尽管项目里的逻辑不断的变为复杂,但是rxjava异步代码依然简洁易懂。
retrofit2的优势,简洁功能却强劲,自定义GSON解析,添加拦截器等
mvp的优势,结构清晰,代码解耦,维护性较高
四个相结合,组成项目的优美整体架构。
dependencies {
// Net
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-scalars:2.0.0-beta4'
compile 'com.squareup.okhttp3:okhttp:3.2.0'
// Annotation
compile 'com.google.dagger:dagger:2.0.2'
apt 'com.google.dagger:dagger-compiler:2.0.2'
provided 'org.glassfish:javax.annotation:10.0-b28'
compile 'com.jakewharton:butterknife:7.0.1'
// Rx
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.5'
}
在build.gradle文件下,添加对应的版本。
@Inject
MainActivityPresenter mPresenter;
DaggerMainComponent.builder()
.appComponent(appComponent)
.build()
.inject(this);
这是在MainActivity中,为了获得MainActivityPresenter的实例,通过@Inject去容器里查询所有构造器用@Inject标注的类,如果找到了便取出实例来用之。MainActivity必须执行注册操作,表明我需要用到我的注射器,去得到目标类。
@Inject
public MainActivityPresenter(Api api) {
this.api = api;
}
这是在MainActivityPresenter中的构造函数,可以看到了,标明了@Inject,我的理解就是,这个类就会加入到容器之中。但是会发现,这个构造函数还有个类Api的参数,那么这个类也需要在容器中获得,但是去哪找呢?这就需要一个component,我的理解为一个管道,与容器相连接查询目标类的东西。
@Component(modules = {AppModule.class, ApiModule.class})
public interface AppComponent {
Context getContext();
Api getApi();
}
在AppComponent中,通过一个Api.getApi标明这里可以获取Api类,便会到与之关联的module中去查询,
@Module
public class AppModule {
private Context context;
public AppModule(Context context) {
this.context = context;
}
@Provides
public Context provideContext() {
return context;
}
}
@Module
public class ApiModule {
@Provides
public OkHttpClient provideOkHttpClient() {
LoggingInterceptor logging = new LoggingInterceptor(new MyLog());
logging.setLevel(LoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS)
.connectTimeout(20 * 1000, TimeUnit.MILLISECONDS)
.readTimeout(20 * 1000, TimeUnit.MILLISECONDS)
.retryOnConnectionFailure(true) // 失败重发
.addInterceptor(new HeaderInterceptor())
.addInterceptor(logging);
return builder.build();
}
@Provides
protected Api provideService(OkHttpClient okHttpClient) {
return Api.getInstance(okHttpClient);
}
public static class MyLog implements LoggingInterceptor.Logger {
@Override
public void log(String message) {
LogUtils.i("oklog: " + message);
}
}
}
可以看到provideService这个方法可以获取到Api类,但是这个也有参数OkHttpClient,然后又到容器中查找,以此类推,便完成一次注射了。
得到Api后,肯定要用他干什么的,于是便用到了rxjava与retrofit2了。
public class Api {
public static Api instance;
private ApiService service;
public Api(OkHttpClient okHttpClient) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constant.API_BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 添加Rx适配器
.addConverterFactory(GsonConverterFactory.create()) // 添加Gson转换器
.client(okHttpClient)
.build();
service = retrofit.create(BookApiService.class);
}
public static Api getInstance(OkHttpClient okHttpClient) {
if (instance == null)
instance = new Api(okHttpClient);
return instance;
}
public Observable getRecommend(String gender) {
return service.getRecomend(gender);
}}
public interface BookApiService {
@GET("/recommend")
Observable getRecomend(@Query("gender") String gender);}
获取到Api就可以在presenter层做相关的异步操作了
@Override
public void login(String uid, String token, String platform) {
Subscription rxSubscription = bookApi.login(uid, token, platform).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer() {
@Override
public void onNext(Login data) {
if (data != null && mView != null && data.ok) {
mView.loginSuccess();
LogUtils.e(data.user.toString());
}
}
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
LogUtils.e("login" + e.toString());
}
});
addSubscrebe(rxSubscription);
}
public interface MainContract {
interface View extends BaseContract.BaseView {
void loginSuccess();
}
interface Presenter extends BaseContract.BasePresenter {
void login(String uid, String token, String platform);
}
}
public interface BaseContract {
interface BasePresenter {
void attachView(T view);
void detachView();
}
interface BaseView {
void showError();
void complete();
}
}
这是模拟登陆设置的接口,供参考。