Android 教你一步步搭建MVP,附项目源码

@Override

public void onFailure(Call<Book> call, Throwable t) {

}

});`




这里我们可以看到,先新建了一个Retrofit对象,然后给它设置一个我们前面说的baseUrl`https://api.douban.com/v2/`.因为接口返回的数据不是我们需要的实体类,我们需要调用addConverterFactory方法进行转换。由于返回的数据为json类型,所以在这个方法中传入Gson转换工厂`GsonConverterFactory.create(new GsonBuilder().create())`,这里我们需要在studio中添加Gson的依赖:



> compile 'com.squareup.retrofit2:converter-gson:2.1.0'



然后我们调用retrofit的create方法并传入上面我们定义的接口的文件名RetrofitService.class,就可以得到RetrofitService 的实体对象。有了这个对象,我们就可以调用里面之前定义好的请求方法了。比如:



Call<Book> call = service.getSearchBook("金瓶梅", null, 0, 1);




它会返回一个Call实体类,然后就可以调用Call的enqueue方法进行异步请求,在enqueue方法中传入一个回调CallBack,重写里面的onResponse和  

onFailure方法,也就是请求成功和失败的回调方法。当成功时,它会返回Response,里边封装了请求结果的所有信息,包括报头,返回码,还有主体等。比如调用它的body()方法就可获得Book对象,也就是我们需要的数据。这里我们就把返回的Book,显示屏幕上。如下图:



![](https://upload-images.jianshu.io/upload_images/3057657-370847c4f1e78557.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/360)



好了,到这里我们就基本了解了Retrofit的整个工作流程。



> #### 3.RxJava



我们这篇文章主要介绍搭建整体网络请求框架,所以关于RxJava的基础知识,我这就不再详细介绍了,网上也有很多文章,对RxJava还不是很了解的同学,推荐你看一下扔物线的这篇文章[给 Android 开发者的 RxJava 详解](

)



下面我们来看一下RxJava和retrofit的结合使用,为了使Rxjava与retrofit结合,我们需要在Retrofit对象建立的时候添加一句代码`addCallAdapterFactory(RxJavaCallAdapterFactory.create())`,当然你还需要在build.gradle文件中添加如下依赖:



>         compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'



完整的代码如下:



`Retrofit retrofit = new Retrofit.Builder()

    .baseUrl("https://api.douban.com/v2/")

    .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().create()))

    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//支持RxJava

    .build();` 



然后我们还需要修改RetrofitService 中的代码:



`public interface RetrofitService {

@GET("book/search")

Observable<Book> getSearchBook(@Query("q") String name,

                                @Query("tag") String tag, @Query("start") int start,

                                @Query("count") int count);` 



可以看到,在原来的RetrofitService 中我们把getSearchBook方法返回的类型Call改为了Observable,也就是被观察者。其他都没变。然后就是创建RetrofitService 实体类:



RetrofitService service = retrofit.create(RetrofitService.class);




和上面一样,创建完RetrofitService ,就可以调用里面的方法了:



Observable<Book> observable = service.getSearchBook("金瓶梅", null, 0, 1);




其实这一步,就是创建了一个rxjava中observable,即被观察者,有了被观察者,就需要一个观察者,且订阅它:



`observable.subscribeOn(Schedulers.io())//请求数据的事件发生在io线程

      .observeOn(AndroidSchedulers.mainThread())//请求完成后在主线程更显UI

      .subscribe(new Observer<Book>() {//订阅

          @Override

          public void onCompleted() {

              //所有事件都完成,可以做些操作。。。

          }

          @Override

          public void onError(Throwable e) {

              e.printStackTrace(); //请求过程中发生错误

          }

          @Override

          public void onNext(Book book) {//这里的book就是我们请求接口返回的实体类 

          }

       }` 



在上面中我们可以看到,事件的消费在Android主线程,所以我们还要在build.gradle中添加如下依赖:



>         compile 'io.reactivex:rxandroid:1.2.0'



这样我们就引入了RxAndroid,RxAndroid其实就是对RxJava的扩展。比如上面这个Android主线程在RxJava中就没有,因此要使用的话就必须得引用RxAndroid。



> 4.实践

> ----



接下来我们就看看,在一个项目中上面三者是如何配合的。我们打开Android Studio,新建一个项目取名为MVPDemo。这个demo的功能也很简单,就是点击按钮调用上面的那个测试接口,将请求下来书的信息显示在屏幕上。首先我们来看一下这个工程的目录结构:



![](https://upload-images.jianshu.io/upload_images/3057657-4ed4d34dad709ec9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/461)



我们可以看到,在项目的包名下,我们建了三个主要的文件夹:app、service、ui。当然根据项目的需要你也可以添加更多其他的文件夹,比如一些工具类等。其中app文件夹中可以建一个Application类,用于设置应用全局的一些属性,这里为了使项目更加简单就没有添加;然后,我们再来看看ui文件夹下,这个文件夹下主要放一些关于界面的东西。在里面我们又建了三个文件夹:activity、adapter、fragment,我想看名字你就清楚里面要放什么了。最后我们在重点看看service文件夹中的东西。首先我们来看看里面重要的两个类:RetrofitHelper和RetrofitService。RetrofitHelper主要用于Retrofit的初始化:



`public class RetrofitHelper {

private Context mCntext;



OkHttpClient client = new OkHttpClient();

GsonConverterFactory factory = GsonConverterFactory.create(new GsonBuilder().create());

private static RetrofitHelper instance = null;

private Retrofit mRetrofit = null;

public static RetrofitHelper getInstance(Context context){

    if (instance == null){

        instance = new RetrofitHelper(context);

    }

    return instance;

}

private RetrofitHelper(Context mContext){

    mCntext = mContext;

    init();

}



private void init() {

    resetApp();

}



private void resetApp() {

    mRetrofit = new Retrofit.Builder()

            .baseUrl("https://api.douban.com/v2/")

            .client(client)

            .addConverterFactory(factory)

            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())

            .build();

}

public RetrofitService getServer(){

    return mRetrofit.create(RetrofitService.class);

}

}`




代码并不复杂,其中resetApp方法,就是前面介绍的Retrofit的创建,getServer方法就是为了获取RetrofitService接口类的实例化。然后定义了一个静态方法getInstance用于获取自身RetrofitHelper的实例化,并且只会实例化一次。



接下来,看一下RetrofitService,其中代码还是上面一样:



`public interface RetrofitService {

@GET("book/search")

Observable<Book> getSearchBooks(@Query("q") String name,

                                @Query("tag") String tag, @Query("start") int start,

                                @Query("count") int count);

}`




然后我们依次来看一下service文件夹下的四个文件夹:entity、manager、presenter和view。其中entity下放我们请求的实体类,这里就是Book。接下来我们来看一下manager中DataManager。这个类其实就是为了让你更方便的调用RetrofitService 中定义的方法:



`public class DataManager {

private RetrofitService mRetrofitService;

public DataManager(Context context){

    this.mRetrofitService = RetrofitHelper.getInstance(context).getServer();

}

public  Observable<Book> getSearchBooks(String name,String tag,int start,int count){

    return mRetrofitService.getSearchBooks(name,tag,start,count);

}

}`




可以看到,在它的构造方法中,我们得到了RetrofitService 的实例化,然后定义了一个和RetrofitService 中同名的方法,里面其实就是调用RetrofitService 中的这个方法。这样,把RetrofitService 中定义的方法都封装到DataManager 中,以后无论在哪个要调用方法时直接在DataManager 中调用就可以了,而不是重复建立RetrofitService 的实例化,再调用其中的方法。



好了,我们再来看一下presenter和view,我们在前面说过,presenter主要用于网络的请求以及数据的获取,view就是将presenter获取到的数据进行展示。首先我们先来看view,我们看到我们建了两个接口类View和BookView,其中View是空的,主要用于和Android中的View区别开来:



`public interface View {

}`




然后让BookView继承自我们自己定义的View :



`public interface BookView extends View {

void onSuccess(Book mBook);

void onError(String result);

}`




可以看到在里面定义两个方法,一个onSuccess,如果presenter请求成功,将向该方法传入请求下来的实体类,也就是Book,view拿到这个数据实体类后,就可以进行关于这个数据的展示或其他的一些操作。如果请求失败,就会向这个view传入失败信息,你可以弹个Toast来提示请求失败。通常这两个方法比较常用,当然你可以根据项目需要来定义一些其他的方法。接下来我们看看presenter是如何进行网络请求的 。我们也定义了一个基础Presenter:



`public interface Presenter {

void onCreate();



void onStart();//暂时没用到



void onStop();



void pause();//暂时没用到



void attachView(View view);



void attachIncomingIntent(Intent intent);//暂时没用到

}`




里面我们可以看到,定义了一些方法,前面几个onCreate、onStart等方法对应着Activity中生命周期的方法,当然没必要写上Activity生命周期中所有回调方法,通常也就用到了onCreate和onStop,除非需求很复杂,在Activity不同生命周期请求的情况不同。接着我们定义了一个attachView方法,用于绑定我们定义的View。也就是,你想把请求下来的数据实体类给哪个View就传入哪个View。下面这个attachIncomingIntent暂且没用到,就不说了。好了,我们来看一下BookPresenter具体是怎么实现的:



`public class BookPresenter implements Presenter {

private DataManager manager;

private CompositeSubscription mCompositeSubscription;

private Context mContext;

private BookView mBookView;

private Book mBook;

public BookPresenter (Context mContext){

    this.mContext = mContext;

}

@Override

public void onCreate() {

    manager = new DataManager(mContext);

    mCompositeSubscription = new CompositeSubscription();

}



@Override

public void onStart() {



}



@Override

public void onStop() {

    if (mCompositeSubscription.hasSubscriptions()){

        mCompositeSubscription.unsubscribe();

    }

}



@Override

public void pause() {



}



@Override

public void attachView(View view) {

    mBookView = (BookView)view;

}



@Override

public void attachIncomingIntent(Intent intent) {

}

public void getSearchBooks(String name,String tag,int start,int count){

    mCompositeSubscription.add(manager.getSearchBooks(name,tag,start,count)

            .subscribeOn(Schedulers.io())

            .observeOn(AndroidSchedulers.mainThread())

            .subscribe(new Observer<Book>() {

                @Override

                public void onCompleted() {

                    if (mBook != null){

                        mBookView.onSuccess(mBook);

                    }

                }



                @Override
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值