介绍
前面介绍了Dagger2,今天尝试自己的想法去应用了下,说实话很别扭,晚上睡觉思前想后这个的好处。总是有一种似懂非懂,感觉就是,让对象与对象之间产生了一中关联,多个module的provides(供给)的对象,通过1个Component联系起来,我尝试写了2个Demo,一个用了Dagger2,一个没有用,好处自己总结吧
MVP通过一个登陆Demo讲解
MVP优点
来个MVC和MVP图
项目结构
开发逻辑
1:定义Application
public class App extends Application { private static Application app; public static AppComponent appComponent; @Override public void onCreate() { super.onCreate(); app=this; //初始化全局AppComponent,主要对module里面单利和app处于一个生命周期 appComponent = DaggerAppComponent.create(); } public static Application getApplication(){ return app; } public static Context getAppContext(){ return app.getApplicationContext(); } }
2:AppComponent对应2个module
AppModule提供Context和Appcation,ApiModule提供网络请求Retrofit(单利)
@Singleton @Component(modules = {AppModule.class, ApiModule.class}) public interface AppComponent { Context getContext(); Application getApplication(); Retrofit getRetrofit(); Toast getToast(); }
/** * 访问网络的Module */ @Module @Singleton public class ApiModule { public static final String BASE_URL = "https://www.iqshw.com/"; @Provides public Interceptor providesIntercepter() { return new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = chain.proceed(request); String chainControl = request.cacheControl().toString(); if (TextUtils.isEmpty(chainControl)) { chainControl = "public, max-age=60, max-stale=240000"; } return response.newBuilder() .addHeader("Chain-Control", chainControl) .removeHeader("Pragma") .build(); } }; } @Provides public Cache providesCache(Context context) { File httpCacheFile = context.getExternalCacheDir().getAbsoluteFile(); return new Cache(httpCacheFile, 1024 * 10 * 1024); } @Provides @Singleton public OkHttpClient providesOkHttpClient(Interceptor interceptor, Cache cache) { OkHttpClient client = new OkHttpClient.Builder() .cache(cache) .addInterceptor(interceptor) .build(); return client; } @Provides @Singleton public Retrofit providesRetrofit(OkHttpClient client) { Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); return retrofit; } }
3:LoginActivityCompenent创建,依赖于AppCompenent,自己的Module,LoginModule听LoginApi请求对象
注意LoginSingleton因为依赖了AppComponent,所以需要自己定义一个Scope
@LoginSingleton @Component(modules = {LoginModule.class},dependencies = {AppComponent.class}) public interface LoginActivityComponent { void inject(LoginActivity activity); }
4:MVP协议类LoginContract,所有的方法的业务方法都从这里创建
public interface LoginContract { interface LoginMvpView extends BaseMvpView{ void loginSuccess(UserInfo userInfo); String getUser(); String getPass(); } abstract class LoginBasePresenter extends BasePresenter{ public abstract void login(); } }
5:LoginPresenter定义
public class LoginPresenter extends LoginContract.LoginBasePresenter { @Inject public LoginApi loginApi; @Inject public LoginPresenter() { } @Override public void login() { String pass = mView.getPass(); String user = mView.getUser(); if (TextUtils.isEmpty(pass)) { mView.showToastMsg("请输入账号!"); } else if (TextUtils.isEmpty(user)) { mView.showToastMsg("请输入密码!"); } else { mView.showLoadDialog(); Map, String> parameters = new HashMap<>(); parameters.put("username", user); parameters.put("password", pass); parameters.put("enews", "login"); parameters.put("lifetime", "315360000"); loginApi.login(parameters) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer () { @Override public void onCompleted() { mView.hideDialog(); } @Override public void onError(Throwable e) { mView.hideDialog(); mView.showErrorMsg("请求网络失败!"); Log.d("wyz", "e::" + e.getMessage()); } @Override public void onNext(UserInfo info) { Log.d("wyz", "请求数据:" + info); mView.hideDialog(); mView.loginSuccess(info); } }); } } }
6:LoginActivity,主要持有一个LoginPresenter对象即可
public class LoginActivity extends BaseActivity implements LoginContract.LoginMvpView{ @Inject public LoginPresenter loginPresenter; @Inject public Toast toast; private EditText etPass; private EditText etUser; @Override public int getLayoutId() { return R.layout.activity_main; } @Override protected void initView() { progressDialog.setTitle("请稍后"); progressDialog.setMessage("正在加载。。。"); } @Override protected void initData() { //注入 DaggerLoginActivityComponent.builder().appComponent(App.appComponent).build().inject(this); //设置view loginPresenter.setMvpView(this); } @Override protected void findView() { Button btLogin = findViewById(R.id.bt_login); etPass = findViewById(R.id.et_pass); etUser = findViewById(R.id.et_user); btLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { loginPresenter.login(); } }); } @Override public void showLoadDialog() { progressDialog.show(); } @Override public void showErrorMsg(String msg) { Log.d("wyz", "数据错误`消息:" + msg+" "+toast); toast.setText(msg); toast.show(); } @Override public void showToastMsg(String msg) { Log.d("wyz", "数据消息:" + msg+" "+toast); toast.setText(msg); toast.show(); } @Override public void hideDialog() { progressDialog.hide(); } @Override public void loginSuccess(UserInfo userInfo) { toast.setText("UserInfo:" +userInfo); toast.show(); } @Override public String getUser() { return etUser.getText().toString(); } @Override public String getPass() { return etPass.getText().toString(); } }
这是我集成的Dagger2,大体流程是这样的
没用dagger2的RxJava+Retrofit+OkHttp+MVP,我就想知道哪些不舒服,发现有些地方还是有些便利的,例如创建网络请求的时候,只需要一个请求,我必须要写一个单利,createRetrofit,需要的参数,很麻烦,还是dagger2看的舒服些
public class RetrofitCreateHelper { public static final String BASE_URL = "https://www.iqshw.com/"; private Retrofit retrofit; //郁闷还要写单利 dagger2 1个注解就oK private RetrofitCreateHelper(){ createRetrofit(); } public static RetrofitCreateHelper getHelper() { return Holder.holder; } public static class Holder{ public static RetrofitCreateHelper holder=new RetrofitCreateHelper(); } private Interceptor getIntercepter() { return new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Response response = chain.proceed(request); String chainControl = request.cacheControl().toString(); if (TextUtils.isEmpty(chainControl)) { chainControl = "public, max-age=60, max-stale=240000"; } return response.newBuilder() .addHeader("Chain-Control", chainControl) .removeHeader("Pragma") .build(); } }; } private Cache getCache(Context context) { File httpCacheFile = context.getExternalCacheDir().getAbsoluteFile(); return new Cache(httpCacheFile, 1024 * 10 * 1024); } public OkHttpClient getHttpClient(Interceptor interceptor, Cache cache) { OkHttpClient client = new OkHttpClient.Builder() .cache(cache) .addInterceptor(interceptor) .build(); return client; } private void createRetrofit(){ //这里我感受到了Dagger2的好处了 retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(getHttpClient(getIntercepter(),getCache(App.getAppContext())))//这里我感受到了Dagger2的好处了 .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); } public <T> T createApi(Class<T> clazz) { return retrofit.create(clazz); } }
//还是dagger2方便点 public class ToastUtil { private final Toast toast; public static Toast getToast(){ return Hodler.holder.toast; } public static void showToast(String msg){ Toast toast = getToast(); toast.setText(msg); toast.show(); } private ToastUtil(){ toast = Toast.makeText(App.getAppContext(), "", Toast.LENGTH_SHORT); } private static class Hodler{ public static ToastUtil holder=new ToastUtil(); } }
git代码地址