Dagger2之应用篇(Dagger2+RxJava+Retrofit+OkHttp+MVP)-第7章

介绍

        前面介绍了Dagger2,今天尝试自己的想法去应用了下,说实话很别扭,晚上睡觉思前想后这个的好处。总是有一种似懂非懂,感觉就是,让对象与对象之间产生了一中关联,多个module的provides(供给)的对象,通过1个Component联系起来,我尝试写了2个Demo,一个用了Dagger2,一个没有用,好处自己总结吧

MVP通过一个登陆Demo讲解

  • LoginAcitivity,view层,实现LoginContract.LoginMvpView接口(MVP中的Presenter通过接口形式调用view层)
  • LoginModule,Module层,提供了一个LoginApi的请求方法,返回LoginApi
  • LoginPresenter,Presenter层,继承LoginContract.LoginBasePresenter,内部通过login方法

MVP优点

  • 解耦View和Module(Activity再也不那么臃肿了)

  • 逻辑清晰,阅读代码只需要更具指定规则进行阅读(乱写的)
  • 其它自行体会

来个MVC和MVP图

Dagger2之应用篇(Dagger2+RxJava+Retrofit+OkHttp+MVP)-第7章_第1张图片

项目结构

Dagger2之应用篇(Dagger2+RxJava+Retrofit+OkHttp+MVP)-第7章_第2张图片

  • inject包所有的Dagger2的注入类
  • ApiModule类提供网络请求的提供的类,提供Retrofit
  • AppMoudle类通过Context和单利Toast
  • scope包自定义的scope
  • Api包放所有模块对应的Http请求
  • Contract包,mvp对用模块的view和presenter协议

开发逻辑

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代码地址

你可能感兴趣的:(技术学习)