按照Google官方MVP+RxJava+Retrofit2+Dagger2的Demo自己另做一个,进行讲解。

我的师傅给我推荐了一个整体的框架,用于我们公司项目采用。这个就是MVP+RxJava+Retrofit2+Dagger2

我呢,对这个一点也没有接触过。所以,是重头学起的。

对RxJava和Retrofit2我有了解。感觉这两个比较好理解的。我网上看了一些视频和网站后,感觉自己使用起来基本能用,当然,进一步使用我不知道行不行,所以,我还要不断学习。对MVP+RxJava+Retrofit2+Dagger2四个框架推荐几个网址,不过呢,我当初看的网址非常多,非常杂,看一个网站就为了里面对一个小问题的提及,所以推荐的网址还是需要大家来评定的。

1、深入浅出RxJava(一:基础篇) - 大头鬼Bruce - 博客频道 - CSDN.NET

2、RxJava教程

3、RxJava的Demo

4、Rxjava-Android资料汇总(里面有一些推荐的相关跳转网址,很有用的)

5、给 Android 开发者的 RxJava 详解(这个呢,是很多人推荐的,我是第一次看,没懂,看了别的后,回看,懂了一部分,再次回看,基本明白)

6、老罗的android视频第二季里的其中一个,RxJava(百度搜一下,有地方下的,我那个网址链接找不到了,抱歉)

7、Retrofit官网(纯英文,当时我完全看不懂,也没足够的时间猜词,哈哈哈哈)

8、快速Android开发系列网络篇之Retrofit

9、Retrofit的使用教程(一)

10、android retrofit视频(Retrofit的视频蛮多的,比较好找,建议网上看视频学习学习基本的)

11、Android MVP 详解(上)

12、Android App的设计架构:MVC,MVP,MVVM与架构经验谈

13、ANDROID MVP 模式 简单易懂的介绍方式

14、详解Dagger2(注解框架)

15、聊聊 Android 中的依赖注入 - 安卓 - 伯乐在线

16、Dagger——Android上的依赖注入框架

17、Dagger2图文完全教程

18、最简单的Dagger2入门教程

19、Dagger2

20、Dagger2相关网址

21、Dagger2 这次入门就不用放弃了 - _王剑锋 - 博客频道 - CSDN.NET

22、Google官方架构MVP解析与实战 - OPEN 开发经验库

23、Google 官方架构 MVP+Dagger2 架构详解 - 掘金

24、Google官方MVP下载(包括+RxJava和+Dagger2de1)

25、Google官方MVP+Dagger2架构详解【从零开始搭建android框架系列(6)】(这位作者另一篇文章对MVP的理解写的也很棒,你可以找一下,系列里的其他几个)

好了,归于正题,我现在要开始讲了。我做的就是一个上拉加载,下拉刷新的recyclerview的加载数据和点击跳转详情页面的例子。


首先看一下文件目录。

xyrecyclerview包是直接import Module进来的,不用手写。

adapter包,就放了xyrecyclerview的adapter,加载器

api包是服务访问,里面是Retrofit2写的。

bean包是新闻信息的实例类,你在模仿时,直接copy就好了

shownewdetail包新闻细节显示页面(包括了Dagger2、MVP、RxJava的使用)

shownewslist包新闻列表显示页面(包括了Dagger2、MVP、RxJava的使用)

utils包一个功能包,就是webView的一些数据处理的,不用管,直接copy。

其他几个class文件后面一一讲解。



如下讲解,全是个人理解,错了别打我。


首先,要新建一个class,用来继承Application,我的是MyApplication。里面有ApplicationComponent applicationComponent。我讲解一下,代码的写的顺序。

package zjl.com.dagger_mvp_rxjava_demo2;

import android.app.Application;
import android.content.Context;

/**
 * Created by dell on 2016/8/31.
 */
public class MyApplication extends Application {

    private ApplicationComponent applicationComponent;

    public static MyApplication get(Context context){
        return (MyApplication) context.getApplicationContext();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        setGraph();
    }

    private void setGraph() {
        applicationComponent = DaggerApplicationComponent.builder().applicationModule(new ApplicationModule(this)).build();
        applicationComponent.inject(this);//现在没有需要在MyApplication注入的对象,所以这句代码可写可不写
    }

    public ApplicationComponent component(){return applicationComponent;}
}
写的顺序是什么呢,先是继承Application,然后,我要重写onCreate()方法,自定义个方法,setGraph()。用来添加注入器。为什么我要写这个MyApplication呢。因为啊,我是需要某些变量啊、获取几个服务啊,等等的。这些我是在想通过Dagger2来实现简化的想法上,所准备添加的。(我试过,不写,也没关系)。

为了说明效果,我写了给注入器Component用的,注入类ApplicationModule,用来提供Context。

package zjl.com.dagger_mvp_rxjava_demo2;

import android.content.Context;

import dagger.Module;
import dagger.Provides;

/**
 * Created by dell on 2016/8/31.
 */
@Module
public class ApplicationModule {
    private Context context;
    public ApplicationModule(Context context){
        this.context = context;
    }

    @Provides
    public Context provideContext(){
        return context;
    }
}
@Module符号是给Component识别用的,让他找得到。我想提供一个Context对象用(最终目的是为了new 一个Context对象出来嘛),所以就是@Provides下面这段代码,return一个Context对象,这个对象值怎么来,ApplicationModule的构造方法里获取。@Provides是一个识别的符号,告诉别人,用下面的这个方法提供某类对象。

再写一个ApplicationComponent,即注入器。是一个工具。

package zjl.com.dagger_mvp_rxjava_demo2;

import dagger.Component;

/**
 * Created by dell on 2016/8/31.
 */
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {

    void inject(MyApplication myApplication);
}
@Component(modules = {ApplicationModule.class})表示如在MyApplicationzhon中我需要一个Context对象时,可以通过ApplicationComponent的@Component里的某个class中,找到某个@Provides提供相应需要的对象。
 void inject(MyApplication myApplication);
是表示我要提供给谁。比如说:我买本书,Modules是书,Component是卖书的人,@Inject的对象是我。书通过卖书的人的手,到我的手上。回过去看MyApplication,通过DaggerApplicationComponent.builder().applicationModule(new ApplicationModule(this)).build()获取Component对象,并用inject(this)注入。如果以后需要用到某个类对象,就可以通过Application获得。component()方法,就是调用该ApplicationComponent对象。以后会说到,哪里被用到。

然后,是以MVP的框架来写的。那么写个BaseView、BasePresenter、BaseActivity作为基类,用于写具体的类里必定会调用的方法。

BaseView

package zjl.com.dagger_mvp_rxjava_demo2;

/**
 * Created by dell on 2016/8/26.
 */
public interface BaseView {


}

因为我的Demo没有需要的必定会用的方法,所以不用写。

BasePresenter

package zjl.com.dagger_mvp_rxjava_demo2;

import android.support.annotation.NonNull;

/**
 * Created by dell on 2016/8/26.
 */
public interface BasePresenter {
    //绑定view,这个方法将会在activity中调用
    void attachView(@NonNull T view);
    //解绑
    void detachView();
}
用于绑定的,防止内存泄漏哦。

BaseActivity

package zjl.com.dagger_mvp_rxjava_demo2;


import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

/**
 * Created by dell on 2016/8/26.
 */
public abstract class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(initContentView());
        setupComponent((ApplicationComponent) MyApplication.get(this).component());
        initUi();
        initDatas();
        initListener();
        onclick();
    }

    protected abstract void initUi();

    protected abstract void initDatas();

    protected abstract void initListener();

    protected abstract void onclick();

    protected abstract void setupComponent(ApplicationComponent component);//Dagger2绑定

    public abstract int initContentView();

}
写了一些抽象方法,系统一点。


下面开始重点区域部分。


api包,里就两个文件,ApiManagerService里用于写接口,ApiManager实现接口的调用。

来看代码:

先看ApiManagerService

package zjl.com.dagger_mvp_rxjava_demo2.api;



/**
 * Created by dell on 2016/8/10.
 */

import retrofit2.http.GET;
import retrofit2.http.Path;
import rx.Observable;
import zjl.com.dagger_mvp_rxjava_demo2.bean.NewsDetail;
import zjl.com.dagger_mvp_rxjava_demo2.bean.NewsList;

/**
 * @className:ApiManagerService
 * Created by lidong on 2016/3/2.
 */
public interface ApiManagerService {
    @GET("stories/latest")
    Observable getLatestNews();

    @GET("stories/before/{date}")
    Observable getBeforeNews(@Path("date") String date);

    @GET("story/{id}")
    Observable getNewsDetail(@Path("id") int id);

}
根据接口,获取服务,@GET注释,里面写接口的。注意,开头没有“/”的,看getNewsDetail,里,id的@GET为什么有{}呢?因为,他是会变,由参数@Path("id") int id的id值来决定的哦。

再看ApiManager

package zjl.com.dagger_mvp_rxjava_demo2.api;

import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import zjl.com.dagger_mvp_rxjava_demo2.bean.NewsDetail;
import zjl.com.dagger_mvp_rxjava_demo2.bean.NewsList;

/**
 * Created by lidong on 2016/3/2.
 */
public class ApiManager {



    private static final Retrofit sRetrofit = new Retrofit.Builder()
            .baseUrl("http://news-at.zhihu.com/api/4/")
            .addConverterFactory(GsonConverterFactory.create()) // Gson对json数据解析
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 使用RxJava作为回调适配器
            .build();

    private static final ApiManagerService apiManager = sRetrofit.create(ApiManagerService.class);

    public static Observable getLatestNews(){
        return apiManager.getLatestNews();
    }

    public static Observable getBeforeNews(String date){
        return apiManager.getBeforeNews(date);
    }

    public static Observable getNewsDetail(int id) {
        return apiManager.getNewsDetail(id);
    }



}
创建sRetrofit对象,以Gson对json数据解析,使用RxJava进行回调,baseUrl里写主要的不变的总接口地址(注意,结尾必须是"/"作为结尾的哦!!!)

通过Retrofit.create(ApiManagerService.class)获取服务(这都是套路啦)

自己写的静态方法,用户获取相应接口给的数据getLatestNews()、 getBeforeNews(String date)、 getNewsDetail(int id)。


这个比较基础的,如果要用的更复杂,可以加什么@header这些,那个要更深层的学习了。

然后是shownewslist包和shownewdetail包这两个包写法相同。我先按代码编写顺序讲,先是shownewslist包。

ShowNewsListActivity里调用ShowNewsListPresenter,与其关联。ShowNewsListActivity继承了ShowNewsListContract的View接口,ShowNewsListPresenter继承了ShowNewsListContract的Presenter接口。showNewsListModel从ApiManager中获取数据。并提供给ShowNewsListPresenter进行数据处理,再将对应的结果在用ShowNewsListActivity的方法进行显示。ShowNewsListPresenterComponent是ShowNewsListPresenter的注入器,ShowNewsListModule是注入类。

来看代码:

ShowNewsListActivity

package zjl.com.dagger_mvp_rxjava_demo2.shownewslist;


import android.os.Handler;
import android.support.v7.widget.LinearLayoutManager;

import com.jcodecraeer.xrecyclerview.ProgressStyle;
import com.jcodecraeer.xrecyclerview.XRecyclerView;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import butterknife.Bind;
import butterknife.ButterKnife;
import zjl.com.dagger_mvp_rxjava_demo2.ApplicationComponent;
import zjl.com.dagger_mvp_rxjava_demo2.BaseActivity;
import zjl.com.dagger_mvp_rxjava_demo2.R;
import zjl.com.dagger_mvp_rxjava_demo2.adapter.NewsListAdapter;
import zjl.com.dagger_mvp_rxjava_demo2.bean.News;

/**
 * Created by dell on 2016/8/26.
 */
public class ShowNewsListActivity extends BaseActivity implements ShowNewsListContract.View {

    @Bind(R.id.recyclerview)
    XRecyclerView mxRecyclerView;

    private NewsListAdapter newsListAdapter;
    private List listData = new ArrayList<>();

    @Inject
    ShowNewsListPresenter showNewsListPresenter;


    @Override
    protected void initUi() {
        ButterKnife.bind(this);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        mxRecyclerView.setLayoutManager(layoutManager);

        mxRecyclerView.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader);//设置刷新类型
        mxRecyclerView.setLoadingMoreProgressStyle(ProgressStyle.Pacman);//设置加载类型
        //  mRecyclerView.setArrowImageView(R.drawable.iconfont_downgrey);//设置下拉箭头
        mxRecyclerView.setRefreshing(true);
    }

    @Override
    protected void initDatas() {
        newsListAdapter = new NewsListAdapter(this, listData);
        mxRecyclerView.setAdapter(newsListAdapter);

        showNewsListPresenter.attachView(this);
showNewsListPresenter.getNewsListData();
    }

    @Override
    protected void initListener() {
        mxRecyclerView.setLoadingListener(new XRecyclerView.LoadingListener() {
            @Override
            public void onRefresh() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
showNewsListPresenter.getRefreshNewsListData();
                        mxRecyclerView.refreshComplete();
                    }
                }, 1000);
            }

            @Override
            public void onLoadMore() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        showNewsListPresenter.getBeforeNewsListData("20160811");
                        mxRecyclerView.loadMoreComplete();

                    }
                }, 1000);
            }
        });
    }

    @Override
    protected void onclick() {

    }


    @Override
    public void load(ArrayList list) {
        for (int z = 0; z < list.size(); z++) {
            listData.add(list.get(z));
        }
        newsListAdapter.notifyDataSetChanged();

    }

    @Override
    public void refresh(ArrayList list) {
        listData.clear();
        for (int z = 0; z < list.size(); z++) {
            listData.add(list.get(z));
        }
        newsListAdapter.notifyDataSetChanged();

    }

    @Override
    protected void setupComponent(ApplicationComponent component) {
        DaggerShowNewsListPresenterComponent.builder().applicationComponent(component).showNewsListModule(new ShowNewsListModule(this)).build().inject(this);
    }

    @Override
    public int initContentView() {
        return R.layout.activity_main;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        showNewsListPresenter.detachView();
    }
}
按顺序来吧。

initContentView()绑定xml,R.layout.activity_main。

我要创建ShowNewsListPresenter对象,并与其关联。通过Dagger2简化、实现解耦。setupComponent(ApplicationComponent component)方法。

当然,注入对象,就要写Component,要不要写Module呢?这个要看情况的,当提供的对象是第三方库的,要,不是的话,你可以选择用@Inject哦。我这里都有在代码里涉及。

从已写好的代码结果来返回去看,比较好理解。

先看四块代码,了解。

这里,我讲解的顺序有些不同,希望能看懂。一开始,我是一MVP的写法写,那必须要写Presenter,即ShowNewsListPresenter。我们先不看注入,

先看MVP。ShowNewsListPresenter是对数据进行处理,ShowNewsListModel是或取需要的数据,我这里写的是或取接口返回的数据的方法。为了不使系统发生可能的异常,采用异步的方式即RxJava,ShowNewsListModel里的方法,传的值的类型是Observable


ShowNewsListPresenter

package zjl.com.dagger_mvp_rxjava_demo2.shownewslist;


import android.support.annotation.NonNull;

import java.util.ArrayList;

import javax.inject.Inject;

import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
import zjl.com.dagger_mvp_rxjava_demo2.BaseView;
import zjl.com.dagger_mvp_rxjava_demo2.api.ApiManager;
import zjl.com.dagger_mvp_rxjava_demo2.bean.News;
import zjl.com.dagger_mvp_rxjava_demo2.bean.NewsList;

/**
 * Created by dell on 2016/8/26.
 */
public class ShowNewsListPresenter implements ShowNewsListContract.Presenter {

    private ShowNewsListContract.View view;
    private Subscription mSubscription;
    private ArrayList listdata = new ArrayList<>();
    @Inject
    ShowNewsListModel showNewsListModel;
    @Inject
    public ShowNewsListPresenter() {

    }


    @Override
    public void getBeforeNewsListData(String date) {
        mSubscription = showNewsListModel.getBeforeNews(date)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1() {
                    @Override
                    public void call(NewsList newsList) {
                        for (int z = 0; z < newsList.getStories().size(); z++) {
                            listdata.add(newsList.getStories().get(z));
                        }
                        view.load(listdata);
                    }
                }, new Action1() {
                    @Override
                    public void call(Throwable throwable) {
                        System.out.println("-------onFailure" + throwable.getMessage());
                    }
                });
    }

    @Override
    public void getNewsListData() {
        mSubscription =showNewsListModel.getLatestNews()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1() {
                    @Override
                    public void call(NewsList newsList) {
                        listdata.clear();
                        for (int z = 0; z < newsList.getStories().size(); z++) {
                            listdata.add(newsList.getStories().get(z));
                        }
                        view.refresh(listdata);
                    }
                }, new Action1() {
                    @Override
                    public void call(Throwable throwable) {
                        System.out.println("-------onFailure" + throwable.getMessage());
                    }
                });
    }

    @Override
    public void getRefreshNewsListData() {
        mSubscription = showNewsListModel.getLatestNews()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1() {
                    @Override
                    public void call(NewsList newsList) {
                        listdata.clear();
                        for (int z = 0; z < newsList.getStories().size(); z++) {
                            listdata.add(newsList.getStories().get(z));
                        }
                        view.refresh(listdata);
                    }
                }, new Action1() {
                    @Override
                    public void call(Throwable throwable) {
                        System.out.println("-------onFailure" + throwable.getMessage());
                    }
                });
    }

    @Override
    public void attachView(@NonNull ShowNewsListContract.View view) {
        this.view = view;
    }

    @Override
    public void detachView() {

        if (mSubscription != null && !mSubscription.isUnsubscribed()) {
            mSubscription.unsubscribe();
        }
        view = null;
    }

}
ShowNewsListPresenter里哪里用到了RxJava呢?对RxJava有所了解的,很清楚的看出是在getBeforeNewsListData(String date) ,getNewsListData() ,getRefreshNewsListData()里。以getBeforeNewsListData(String date) 方法,为例。一句句说明干什么用。

mSubscription是什么?

private Subscription mSubscription;
RxJava中有个叫做Subscription的接口,可以用来取消订阅.只需要调用unsubscribe就可以取消订阅,那么如何得到一个Subscription对象呢?
其实很简单:
Observable.subscribe()方法可以返回一个Subscription的对象,即我们每次订阅都会返回.
感觉Subscription就像一个订单,你下单了就会生成一个订单,而你也可以用这个订单取消订单。

showNewsListModel.getLatestNews()
调用showNewsListModel的getLatestNews()方法向接口获取数据。

 .subscribeOn(Schedulers.io())
获取数据这一步是开启新线程,在新线程里执行。

.observeOn(AndroidSchedulers.mainThread())
对接口返回的数据的处理,是在主线程执行。

.subscribe(new Action1() {
                    @Override
                    public void call(NewsList newsList) {
                        for (int z = 0; z < newsList.getStories().size(); z++) {
                            listdata.add(newsList.getStories().get(z));
                        }
                        view.load(listdata);
                    }
                }, new Action1() {
                    @Override
                    public void call(Throwable throwable) {
                        System.out.println("-------onFailure" + throwable.getMessage());
                    }
                });
    }
对接口返回的数据的处理,在subscribe()方法中写,Action1方法里重写call(),这个是简化了写法,替代了,onNext()、onError()、onComplete()方法。

重写call()方法,代码里用for循环遍历list,是为了处理数据,再通过

view.load(listdata);
方法,调用ShowNewsListActivity里的load(ArrayList list)方法,对V进行UI对应更改。

然后是attachView(@NonNull ShowNewsListContract.View view)、detachView()方法,这两个方法是什么用的呢?是为了防止内存泄漏的哦。当Activity结束时,要同时结束Presenter,防止,重新使用Activity时,上个Presenter还未结束。所以要将Presenter绑定到Activity,随着Activity销毁,OnDestory()而结束。

ShowNewsListModel

 
  
package zjl.com.dagger_mvp_rxjava_demo2.shownewslist;


import javax.inject.Inject;

import rx.Observable;
import zjl.com.dagger_mvp_rxjava_demo2.api.ApiManager;
import zjl.com.dagger_mvp_rxjava_demo2.bean.NewsList;

/**
 * Created by dell on 2016/8/26.
 */

public class ShowNewsListModel {

    @Inject
    public ShowNewsListModel(){}

    Observable getLatestNews(){
        return ApiManager.getLatestNews();
    }

   Observable getBeforeNews(String date){
        return ApiManager.getBeforeNews(date);
    }
}
对MVP有了解的,知道。V接收用户的指令,调用P,P有必要时,就向M获取数据,M将获取的数据再给P,P处理后,反馈给V中去显示。(这是我理解的MVP)。我们回看ShowNewsListActivity,看看哪里调用了P。
在initDatas()方法中,初始化数据。
 
  
 @Override
    protected void initDatas() {
        newsListAdapter = new NewsListAdapter(this, listData);
        mxRecyclerView.setAdapter(newsListAdapter);

        showNewsListPresenter.attachView(this);
        showNewsListPresenter.getNewsListData();
    }
在这里就执行了
showNewsListPresenter.attachView(this);
将Presenter绑定Activity,
 
  
showNewsListPresenter.getNewsListData();
这句话,就调用了P,让ShowNewsListPresenter调用相应的方法去获取新闻数据。

这样MVP的使用应该能理解吗?(我第一次写,不是很会讲,没看懂,真是对不起了。)
接下来我讲Dagger2的使用。
 
  
ShowNewsListActivity要让ShowNewsListPresenter调用方法,就需要对ShowNewsListPresenter实例化。为了解耦,避免ShowNewsListPresenter有改动,导致ShowNewsListActivity也要随之改动,所以,用Dagger2实现注入。
既然要实现注入,Component必不可少。所以就有了ShowNewsListPresenterComponent。
看代码:
 
  

ShowNewsListPresenterComponent

package zjl.com.dagger_mvp_rxjava_demo2.shownewslist;


import dagger.Component;
import zjl.com.dagger_mvp_rxjava_demo2.ApplicationComponent;

/**
 * Created by dell on 2016/9/1.
 */
@Component(dependencies = ApplicationComponent.class,modules = ShowNewsListModule.class)
public interface ShowNewsListPresenterComponent {
    void inject(ShowNewsListActivity showNewsListActivity);
}

我这里void inject(ShowNewsListActivity showNewsListActivity);是表明要注入到ShowNewsListActivity中。看代码里有一句
 
  
@Component(dependencies = ApplicationComponent.class,modules = ShowNewsListModule.class)
依赖上层的Component,实例化ShowNewsPresenter时需要Module,ShowNewsListModule中提供的某些对象。而其实,我这里并未用到ShowNewsListModule.class,只是演示一下Module怎么写。在NewDetailPresenterComponent中我特意写成需要用到的,到时候看一下。

ShowNewsListModule
package zjl.com.dagger_mvp_rxjava_demo2.shownewslist;

import dagger.Module;
import dagger.Provides;

/**
 * Created by dell on 2016/8/30.
 */
@Module
public class ShowNewsListModule {

    private final ShowNewsListContract.View view;
    public ShowNewsListModule(ShowNewsListContract.View view){
        this.view = view;
    }
}

看ShowNewsListPresenter中有

 @Inject
    public ShowNewsListPresenter() {

    }
 @Inject是识别的,ShowNewsListActivity中需要一个ShowNewsListPresenter对象,通过Component去找哪里有对应的对象生成,发现,ShowNewsListPresenter的构造方法上有一个 @Inject符号,就找到这个对象,自动实例化,其中还需要一个ShowNewsListModel对象,同样用@Inject注入,ShowNewsListPresenterComponent会自动去查找哪里有提供对象,会在ShowNewsListModel的构造方法中,找到,最终生成了ShowNewsListPresenter对象。

回来再看,ShowNewsListActivity,需要实例化Component,进一步注入对象,这个时候,就要重写setupComponent(ApplicationComponent component)方法。

@Override
    protected void setupComponent(ApplicationComponent component) {
        DaggerShowNewsListPresenterComponent.builder().applicationComponent(component).showNewsListModule(new ShowNewsListModule(this)).build().inject(this);
    }
首先在ShowNewsListPresenterComponent和ShowNewsListModule写好后,需要rebuild一下项目,自动生成DaggerShowNewsListPresenterComponent文件,在进一步实例化,依赖的Component和Module,最后注入进Activity。

OK,ShowNewsListPresenter注入成功。

那Module怎么使用呢,我的ShowNewsListModule没有被使用,所以我特地写了个会被使用的。请看shownewdetail包,MVP的写法相同,我就不写了,我讲一下Dagger2注入。

NewDetailPresenterComponent写法相同。

package zjl.com.dagger_mvp_rxjava_demo2.shownewdetial;


import dagger.Component;
import zjl.com.dagger_mvp_rxjava_demo2.ApplicationComponent;

/**
 * Created by dell on 2016/9/1.
 */
@Component(dependencies = ApplicationComponent.class,
        modules = NewDetailModule.class)
public interface NewDetailPresenterComponent {
    void inject(NewDetailActivity newDetailActivity);
}
NewDetailPresenter的构造方法和ShowNewsListPresenter的有些不同,有参数。

package zjl.com.dagger_mvp_rxjava_demo2.shownewslist;


import android.support.annotation.NonNull;

import java.util.ArrayList;

import javax.inject.Inject;

import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
import zjl.com.dagger_mvp_rxjava_demo2.BaseView;
import zjl.com.dagger_mvp_rxjava_demo2.api.ApiManager;
import zjl.com.dagger_mvp_rxjava_demo2.bean.News;
import zjl.com.dagger_mvp_rxjava_demo2.bean.NewsList;

/**
 * Created by dell on 2016/8/26.
 */
public class ShowNewsListPresenter implements ShowNewsListContract.Presenter {

    private ShowNewsListContract.View view;
    private Subscription mSubscription;
    private ArrayList listdata = new ArrayList<>();
    @Inject
    ShowNewsListModel showNewsListModel;
    @Inject
    public ShowNewsListPresenter() {

    }


    @Override
    public void getBeforeNewsListData(String date) {
        mSubscription = showNewsListModel.getBeforeNews(date)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1() {
                    @Override
                    public void call(NewsList newsList) {
                        for (int z = 0; z < newsList.getStories().size(); z++) {
                            listdata.add(newsList.getStories().get(z));
                        }
                        view.load(listdata);
                    }
                }, new Action1() {
                    @Override
                    public void call(Throwable throwable) {
                        System.out.println("-------onFailure" + throwable.getMessage());
                    }
                });
    }

    @Override
    public void getNewsListData() {
        mSubscription =showNewsListModel.getLatestNews()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1() {
                    @Override
                    public void call(NewsList newsList) {
                        listdata.clear();
                        for (int z = 0; z < newsList.getStories().size(); z++) {
                            listdata.add(newsList.getStories().get(z));
                        }
                        view.refresh(listdata);
                    }
                }, new Action1() {
                    @Override
                    public void call(Throwable throwable) {
                        System.out.println("-------onFailure" + throwable.getMessage());
                    }
                });
    }

    @Override
    public void getRefreshNewsListData() {
        mSubscription = showNewsListModel.getLatestNews()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1() {
                    @Override
                    public void call(NewsList newsList) {
                        listdata.clear();
                        for (int z = 0; z < newsList.getStories().size(); z++) {
                            listdata.add(newsList.getStories().get(z));
                        }
                        view.refresh(listdata);
                    }
                }, new Action1() {
                    @Override
                    public void call(Throwable throwable) {
                        System.out.println("-------onFailure" + throwable.getMessage());
                    }
                });
    }

    @Override
    public void attachView(@NonNull ShowNewsListContract.View view) {
        this.view = view;
    }

    @Override
    public void detachView() {

        if (mSubscription != null && !mSubscription.isUnsubscribed()) {
            mSubscription.unsubscribe();
        }
        view = null;
    }

}

NewDetailPresenterComponent会自动去找提供对象的方法,找到了NewDetailModule。

package zjl.com.dagger_mvp_rxjava_demo2.shownewdetial;

import dagger.Module;
import dagger.Provides;
import zjl.com.dagger_mvp_rxjava_demo2.shownewslist.ShowNewsListContract;

/**
 * Created by dell on 2016/8/31.
 */
@Module
public class NewDetailModule {
    private final NewDetailContract.View view;
    private int id;
    public NewDetailModule(NewDetailContract.View view,int id){
        this.view = view;
        this.id = id;
    }

    @Provides
    public int provideid(){
        return id;
    }
}

provideid()方法,提供了参数int id。

在NewDetailActivity里setupComponent(ApplicationComponent component)方法中,对NewDetailModule的实例化时,需要传递进一个int型参数,就是用于实例化NewDetailPresenter的。

@Override
    protected void setupComponent(ApplicationComponent component) {
        DaggerNewDetailPresenterComponent.builder().applicationComponent(component).newDetailModule(new NewDetailModule(this, getIntent().getIntExtra("new", 0))).build().inject(this);
    }


综上,例子就写完了。希望对大家能有一丢丢的帮助。首次写博客,写的不好请见谅。

项目地址









你可能感兴趣的:(android)