Android -- 带你从源码角度领悟Dagger2入门到放弃(三)

1, 前面两篇文章咱们知道了怎么使用经常使用的四种标签,如今咱们结合咱们本身的项目中去简单的使用java

  在咱们搭建项目的时候,通常会建立本身的Application,在里面进行一些初始化如一些第三方的GreenDao、ShareSDK等等,再或者提供一些经常使用的属性初始化:例如初始化屏幕的宽高度、初始化SPUtils工具类等,因此咱们能够建立App类继承自Application(这里我只写了简单的App对象建立,没有写其余的任何方法)android

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提供对象的代码app

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类ide

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的对象(固然这个需求在现实中是不成立的),咱们就能够这样写Moduleui

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对象了。this

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

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两个都是不容易上手的,麻蛋,本身思路写的也混乱了,祝你们早日拖坑)。

相关文章
相关标签/搜索