Retrofit2-RxJava-Dagger2-MVP完美封装

如果对 Retrofit2+RxJava 封装还不是很了解的话
可以参考下:
//www.greatytc.com/p/17e3e3102c1f
如果对Dagger2 还不是很了解,可以参考下:
//www.greatytc.com/p/cd2c1c9f68d4
如果对mvp还不是很了解,可以自己百度下,很多的,我就不贴出了.
下面我简单讲述下:
请先看下目录结构:

com
└── javalong
└── rrdm
├── activity
│   ├── component
│   │   ├── LoginActivityComponent.java
│   │   └── MainActivityComponent.java
│   ├── iview
│   │   ├── ILoginView.java
│   │   └── IMainView.java
│   ├── LoginActivity.java
│   ├── MainActivity.java
│   ├── module
│   │   ├── LoginActivityModule.java
│   │   └── MainActivityModule.java
│   └── presenter
│       ├── LoginPresenter.java
│       └── MainPresenter.java
├── app
│   ├── annotation
│   │   └── ActivityScope.java
│   ├── AppBaseActivity.java
│   ├── AppBaseApplication.java
│   ├── component
│   │   └── AppComponent.java
│   ├── iview
│   │   └── MvpView.java
│   ├── module
│   │   └── AppModule.java
│   └── presenter
│       └── AppPresenter.java
└── retrofit
├── ResponseMessageBean.java
├── RetrofitHelper.java
├── ServerApi.java
├── TWGsonConverterFactory.java
├── TWGsonRequestBodyConverter.java
├── TWGsonResponseBodyConverter.java
└── TWJavaCallAdapterFactory.java

这里我就不对mvp,dagger2和Retrofit2+Rxjava过多介绍了.这里就介绍下具体的封装.
我这里是一个Presenter和一个Activity(View)相互对应,所以我让Presenter直接在基类中注入.对其进行统一管理:
AppPresenter.Java:

/** 
 * Created by javalong on 16-12-27. 
 * presenter基类 
 */  
public abstract class AppPresenter<V extends MvpView>{  
    @Inject  
    protected V mvpView;  
  
    public AppPresenter(V mvpView) {  
        this.mvpView = mvpView;  
    }  
  
    public abstract void attach();  
    public abstract void detach();  
}  

AppBaseActivity.java--->所有Activity的基类,对presenter进行统一处理.

/** 
 * Created by javalong on 16-12-27. 
 */  
  
public abstract class AppBaseActivity<T extends AppPresenter> extends AppCompatActivity {  
    @Inject  
    protected T mPresenter;  
  
    @Override  
    protected void onCreate(@Nullable Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        initInjects();  
        mPresenter.attach();  
    }  
  
    protected abstract void initInjects();  
  
    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        mPresenter.detach();  
    }  
  
    protected AppComponent getAppComponent(){  
        return AppBaseApplication.getInstance().getAppComponent();  
    }  
}  

AppBaseActivity中引用了AppComponent.这个需要在AppBaseApplication进行初始化.Component是dagger2依赖注入的基础.

AppBaseApplication.java

/** 
 * Created by javalong on 16-12-27. 
 */  
  
public class AppBaseApplication extends Application {  
  
    private static AppBaseApplication instance;  
  
    public static AppBaseApplication getInstance() {  
        return instance;  
    }  
  
    AppComponent appComponent;  
  
    public AppComponent getAppComponent() {  
        return appComponent;  
    }  
  
    @Override  
    public void onCreate() {  
        super.onCreate();  
        instance = this;  
        if (appComponent == null) {  
            appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();  
        }  
    }  
}  

如果不熟悉Dagger2的童鞋,可能会发现没有DaggerAppComponent这个类,不要慌,请'Make Project'编译下项目.DaggerAppComponent会自动生成.DaggerAppComponent其实是根据我们写的AppComponent接口生成的一个类,下面我们先看下AppComponent.

@Singleton  
@Component(modules = AppModule.class)  
public interface AppComponent {  
    Context getContext();  
    ServerApi getServerApi();  
}  

AppComponent这个接口其实很简单.这里记得要加上@Scope注解(@Singleton是@Scope的一种)使Component和Module中provide出来的对象联系起来.
关于@Scope注解的含义我这里就不过多介绍了,大家可以参考我上面推荐的文章.写的很不错.
接下来看下AppModule中提供了哪些依赖

@Module  
public class AppModule {  
  
    private Context mContext;  
  
    public AppModule(Context context) {  
        this.mContext = context;  
    }  
  
    @Provides @Singleton  
    Context provideContext(){  
        return mContext;  
    }  
  
    @Provides @Singleton  
    ServerApi provideServerApi(Context context){  
        RetrofitHelper.init(context);  
        return RetrofitHelper.getApi();  
    }  
  
}  

这里的@Singleton 和前面AppComponent的@Singleton 相互连接,让我们造成了单例的假象.其实@Singleton并没有单例的作用,是因为
和AppComponent一起使用,AppComponent只创建了一次,所以产生'单例'这个现象.(我这里又重复得说了一边,汗~~)
AppComponent和AppModule请根据自己项目的详细情况来进行封装,由于我这个demo比较简单,所以只@Provides 了2个对象出来.

下面我来详细介绍下Activity和Presenter之间的封装.
首先我这里先说明下,我这里的一个Activity,对应着1个view,1个presenter,1个component,1个module.
可能封装的不是很好,没有领悟到mvp的精髓,但是对我来说更加清晰.
MainActivity.java

public class MainActivity extends AppBaseActivity<MainPresenter> implements IMainView{  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        mPresenter.test();  
    }  
  
    @Override  
    protected void initInjects() {  
        DaggerMainActivityComponent.builder()  
                .appComponent(getAppComponent())  
                .mainActivityModule(new MainActivityModule(this))  
                .build()  
                .inject(this);  
    }  
  
  
    @Override  
    public void showMainMessage() {  
        ((TextView)findViewById(R.id.tv_test))  
                .setText("你好 dagger");  
        findViewById(R.id.bt_login)  
        .setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                LoginActivity.start(MainActivity.this);  
                MainActivity.this.finish();  
            }  
        });  
    }  
}  

MainActivity必须继承AppBaseActivity,然后传入泛型,即对应的Presenter的类型.在initInjects中必须完成Dagger2的注入操作,因为在AppBaseActivity中的Presenter需要
注入,如果不注入,在基类中调用mPresenter.attach会出错.
当你使用Dagger2的时候,其实很明显会暴露他的一个缺点,必须要编译后,才能产生对应的Dagger**Component.当然相对于他的好处来讲,这点还是可以忍受的.
前面提到了必须要对基类中的Presenter进行注入,那么到底注入的是什么呢?这里我以MainPresenter为例.

public class MainPresenter extends AppPresenter<IMainView>{  
  
    @Inject  
    public MainPresenter(IMainView mvpView) {  
        super(mvpView);  
    }  
  
    @Override  
    public void attach() {  
  
    }  
  
    @Override  
    public void detach() {  
  
    }  
  
    public void test() {  
        mvpView.showMainMessage();  
    }  
}  

MainActivityModule.java

@Module  
public class MainActivityModule  {  
  
    private IMainView mainView;  
  
    public MainActivityModule(IMainView mainView) {  
        this.mainView = mainView;  
    }  
  
    @Provides @ActivityScope IMainView provideIMainView(){  
        return mainView;  
    }  
  
    /** 
     * 这种方式,和直接在MainPresenter构造方法上添加@Inject是一样的 
     * 二选一即可. 
     */  
//    @Provides @ActivityScope MainPresenter provideMainPresenter(IMainView mainView){  
//        return new MainPresenter(mainView);  
//    }  
}  

看注释,这里有2种方式可以完成MainPresenter的注入,一种是直接在MainPreenter的构造方法上加上@Inject,一种是在对应的Module中使用
@Provides 把MainPresenter提供出来. 至于@ActivityScope其实是和前面@Scope一样的,我这里就不过多介绍了.
最关键的一步:
MainActivityComponent.java

@ActivityScope  
@Component(dependencies = AppComponent.class,modules = MainActivityModule.class)  
public interface MainActivityComponent{  
    /** 
     * @param mainView 
     * 这里必须使用MainActivity,不能使用IMain接口 
     * 否则会造成@Inject注入失败 
     */  
    void inject(MainActivity mainView);  
} 

必须在对应的Component提供注入方法(名字不一定叫inject).
MainActivity.java 部分代码

@Override  
   protected void initInjects() {  
       DaggerMainActivityComponent.builder()  
               .appComponent(getAppComponent())  
               .mainActivityModule(new MainActivityModule(this))  
               .build()  
               .inject(this);  
   }  

这样才完成了注入.
DaggerMainActivityComponent中会先对AppBaseActivity进行注入,然后再对MainActivity进行注入.
这里我简单的讲述了封装,如果还有什么不懂的地方可以再交流~~~github: https://github.com/javalong/Retrofit2-RxJava-Dagger2-MVP

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容