zoukankan      html  css  js  c++  java
  • Android -- 带你从源码角度领悟Dagger2入门到放弃(三)

    1, 前面两篇文章我们知道了怎么使用常用的四种标签,现在我们结合我们自己的项目中去简单的使用

      在我们搭建项目的时候,一般会创建自己的Application,在里面进行一些初始化如一些第三方的GreenDao、ShareSDK等等,再或者提供一些常用的属性初始化:例如初始化屏幕的宽高度、初始化SPUtils工具类等,所以我们可以创建App类继承自Application(这里我只写了简单的App对象创建,没有写其他的任何方法)

    package com.qianmo.rxjavatext;
    
    import android.app.Application;
    
    /**
     * Created by Administrator on 2017/4/21 0021.
     * E-Mail:543441727@qq.com
     */
    
    public class App extends Application {
    
        public static App instance;
    
        public static synchronized App getInstance() {
            return instance;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            instance = this;
        }
    }
    

      一般情况下我们使用很多情况下会使用到上下文环境,而使用Activity的上下文环境会容易发生内存泄漏问题,即该Activity本应该被销毁,但因为外部类持有context对象的引用而导致无法回收Activity,所以这里我们一般使用App中的上下文,这时候我们要向所有的activity提供一个Application的上下文环境对象,再结合我们之前学习的Dagger2知识,先写一下AppModule提供对象的代码

    package com.qianmo.rxjavatext.di;
    
    
    import com.qianmo.rxjavatext.App;
    
    import javax.inject.Singleton;
    
    import dagger.Module;
    import dagger.Provides;
    
    /**
     * Created by Administrator on 2017/4/21 0021.
     * E-Mail:543441727@qq.com
     */
    
    @Module
    public class AppModule {
        public final App application;
    
        public AppModule(App application) {
            this.application = application;
        }
    
        @Provides
        @Singleton
        App provideApplicationContext() {
            return application;
        }
    }
    

      很简单,就是在创建AppModule对象的时候将App对象传递进来,然后添加provideApplicationContext暴露app对象出去,再来看看AppComponent类

    package com.qianmo.rxjavatext.di;
    
    import com.qianmo.rxjavatext.App;
    
    import javax.inject.Singleton;
    
    import dagger.Component;
    
    /**
     * Created by Administrator on 2017/4/21 0021.
     * E-Mail:543441727@qq.com
     */
    @Singleton
    @Component(modules = AppModule.class)
    public interface AppComponent {
    
        //向下层提供上下文环境
        App getContext();
    
    }
    

      这里可能大家有个疑问App getContext();这句代码是干什么的,我们知道Activity中有可能要使用到App上下文环境(虽然这个方法不一定能用到,但是我们还是准备着),这里就是给下层提供这个对象的。那么我们需要在App初始化这个AppComponent对象了

    public class App extends Application {
    
        public static App instance;
        public static AppComponent appComponent;
    
        public static synchronized App getInstance() {
            return instance;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            instance = this;
        }
    
        public static AppComponent getAppComponent() {
            if (appComponent == null) {
                appComponent = DaggerAppComponent.builder().appModule(new AppModule(instance)).build();
            }
            return appComponent;
        }
    }
    

      那么有同学就会有这个疑问什么叫“下层”,用什么表示上下层关系,这里给出的解释是当另一个Activity中的module也想拥有我们的上下文application对象呢?是还要想我们的AppModule一样吗?nonono,这是我们使用dependencies,首先创建Activity的Module,这个类很简单就是提供我们的activity对象,所以代码如下

    package com.qianmo.rxjavatext.di;
    
    import android.app.Activity;
    
    import com.qianmo.rxjavatext.di.scope.ActivityScope;
    
    import javax.inject.Singleton;
    
    import dagger.Module;
    import dagger.Provides;
    
    /**
     * Created by Administrator on 2017/4/21 0021.
     * E-Mail:543441727@qq.com
     */
    @Module
    public class ActivityModule {
        private Activity mActivity;
    
        public ActivityModule(Activity mActivity) {
            this.mActivity = mActivity;
        }
    
        @Provides
        @ActivityScope
        Activity provideActivity() {
            return mActivity;
        }
    }
    

      这里的@ActivityScope就是我们上一篇学习的自定义Scope注解标签,没什么难的,再看看我们的ActivityComponent

    package com.qianmo.rxjavatext.di;
    
    import android.app.Activity;
    
    import com.qianmo.rxjavatext.MainActivity;
    import com.qianmo.rxjavatext.di.scope.ActivityScope;
    
    
    import dagger.Component;
    
    /**
     * Created by Administrator on 2017/4/21 0021.
     * E-Mail:543441727@qq.com
     */
    @ActivityScope
    @Component(dependencies = AppComponent.class,modules = ActivityModule.class)
    public interface ActivityComponent {
    
        //将当前的activity暴露出去
        Activity getActivity();
    
        void inject(MainActivity mainActivity);
    }
    

      dependencies 关键字就是这样使用的 ,例如我们创建student对象,需要App的对象(当然这个需求在现实中是不成立的),我们就可以这样写Module

    package com.qianmo.rxjavatext.di;
    
    import android.app.Activity;
    import android.content.Context;
    
    import com.qianmo.rxjavatext.Student;
    import com.qianmo.rxjavatext.di.scope.ActivityScope;
    
    import javax.inject.Singleton;
    
    import dagger.Module;
    import dagger.Provides;
    
    /**
     * Created by Administrator on 2017/4/21 0021.
     * E-Mail:543441727@qq.com
     */
    @Module
    public class ActivityModule {
        private Activity mActivity;
    
        public ActivityModule(Activity mActivity) {
            this.mActivity = mActivity;
        }
    
        @Provides
        @ActivityScope
        Activity provideActivity() {
            return mActivity;
        }
    
        @Provides
        Student provideStudent(App app) {
            return new Student(app);
        }
    }
    

      我们按Ctrl+F9编译一下,发现我们的程序可以编译过来,正常的话不是应该报错误说App没有注入对象吗,为什么这里是可以运行,这就是dependencies 关键字的用法了,这里我们使用的是AppComponent中的getContext方法的app对象了。

      OK,这里我们在activity中开始调用试试创建Student对象,看看能不能拿到值

    package com.qianmo.rxjavatext;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.CheckBox;
    import android.widget.ListView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.jakewharton.rxbinding.view.RxView;
    import com.jakewharton.rxbinding.widget.RxCompoundButton;
    import com.qianmo.rxjavatext.di.ActivityComponent;
    import com.qianmo.rxjavatext.di.ActivityModule;
    import com.qianmo.rxjavatext.di.DaggerActivityComponent;
    
    import java.util.Collections;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    import javax.inject.Inject;
    
    import rx.Observable;
    import rx.Subscriber;
    import rx.android.schedulers.AndroidSchedulers;
    import rx.functions.Action0;
    import rx.functions.Action1;
    import rx.functions.Func1;
    import rx.schedulers.Schedulers;
    
    public class MainActivity extends AppCompatActivity {
        //需要一个Student对象
        @Inject
        Student mStudent;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initInject();
    
        }
    
        //开始注解
        public void initInject() {
            getActivityComponent().inject(this);
        }
    
        protected ActivityComponent getActivityComponent() {
            return DaggerActivityComponent.builder()
                    .appComponent(App.getAppComponent())
                    .activityModule(getActivityModule())
                    .build();
        }
    
        protected ActivityModule getActivityModule() {
            return new ActivityModule(this);
        }
    }
    

      运行一下看一下打印结果

    04-21 05:36:19.510 2646-2646/com.qianmo.rxjavatext I/System.out: 打印上下文对象呀com.qianmo.rxjavatext.App@34877b0
    

      没问题,说明我们的程序没问题,但是在实际项目中我们都是要编写BaseActivity的,所以我们需要在BaseActivity中这样写

    public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity implements BaseView {
    
        @Inject
        protected T mPresenter;
    
        protected void onCreate(@Nullable Bundle savedInstanceState) {
           
            super.onCreate(savedInstanceState);
            setContentView(getLayout());
    
            initInject();
            if (mPresenter != null)
                mPresenter.attachView(this);
            App.getInstance().addActivity(this);
            initEventAndData();
        }
    
        @Override
        protected void onStart() {
            super.onStart();
    
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
        }
    
    
        /**
         * 添加注解
         */
        protected abstract void initInject();
    
        protected abstract int getLayout();
    
        protected abstract void initEventAndData();
    
    
        protected ActivityComponent getActivityComponent(){
            return  DaggerActivityComponent.builder()
                    .appComponent(App.getAppComponent())
                    .activityModule(getActivityModule())
                    .build();
        }
    
        protected ActivityModule getActivityModule(){
            return new ActivityModule(this);
        }
    }
    

      这里的BaseView和BasePresenter都是我们的MVP的基类,里面很简单的没有说明代码的,我们在具体的activity中怎么使用呢?首先创建MainActivity,在这里调用 mPresenter.attachView(new MainView())方法

    package com.qianmo.rxjavatext.mvp.view;
    
    import com.qianmo.rxjavatext.R;
    import com.qianmo.rxjavatext.base.BaseActivity;
    import com.qianmo.rxjavatext.mvp.presenter.MainPresenterImpl;
    
    /**
     * Created by Administrator on 2017/4/21 0021.
     * E-Mail:543441727@qq.com
     */
    
    public class SecondActivity extends BaseActivity<MainPresenterImpl> {
    
        @Override
        public void showError(String msg) {
    
        }
    
        @Override
        public void useNightMode(boolean isNight) {
    
        }
    
        @Override
        protected void initInject() {
            getActivityComponent().inject(this);
        }
    
        @Override
        protected int getLayout() {
            return R.layout.activity_main;
        }
    
        @Override
        protected void initEventAndData() {
            mPresenter.attachView(new MainView());
        }
    }
    

      再看看重要的MainPresenterImpl类

    package com.qianmo.rxjavatext.mvp.presenter;
    
    import android.content.Context;
    import android.widget.Toast;
    
    
    import com.qianmo.rxjavatext.App;
    import com.qianmo.rxjavatext.base.BasePresenter;
    import com.qianmo.rxjavatext.mvp.view.MainView;
    
    import javax.inject.Inject;
    
    import rx.Observable;
    import rx.Subscriber;
    import rx.Subscription;
    
    
    /**
     * Created by MVPHelper on 2016/11/08
     */
    
    public class MainPresenterImpl implements BasePresenter<MainView> {
    
        private Context context;
    
        @Inject
        public MainPresenterImpl(App app) {
            this.context = app;
        }
    
    
        @Override
        public void attachView(MainView view) {
            Toast.makeText(context, "获取到值了", Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void detachView() {
    
        }
    }
    

      在这里最关键的标注了构造函数MainPresenterImpl,这样我们就注解到了该presenter对象了,看一下效果,ok,基本上我们就是在MVP工程下注解presenter对象了,关键是封装!!!(如果你封装很好了,后面开发使用就很简单,而且也不用单独的写一些Module、component类)

      最后,说一下使用范围对于中小型的项目真心没必要使用Dagger2,还有如果你是Android负责人的话,你还要考虑一下你的Android同事他们上手Dagger2的情况,所以这里还是要试开发情况定(感觉这一片还是没和大家在项目封装的时候讲清楚啊,关键是封装是Dagger两个都是不容易上手的,麻蛋,自己思路写的也混乱了,祝大家早日拖坑)。

  • 相关阅读:
    emberjs初学记要
    自我的一点介绍(七夕礼物)
    JavaScript数据类型
    Vue+Webpack项目配置
    Git知识点整合
    Log4j简单配置解析
    如何明智地向程序员提问
    Navicat连接mysql报错1251
    多表查询sql语句
    PLSQL面向对象
  • 原文地址:https://www.cnblogs.com/wjtaigwh/p/6744939.html
Copyright © 2011-2022 走看看