青岛Android培训
达内青岛山东中心

18300268127

热门课程

山东android:网络请求框架搭建

  • 时间:2018-04-16
  • 发布:山东android
  • 来源:山东android

    山东android:首先,展示一下封装好之后的项目的层级结构。
    1、先创建一个RetrofitApiService.java
    复制代码
    package com.xdw.retrofitrxmvpdemo.http;
    import com.xdw.retrofitrxmvpdemo.model.UserInfo;
    import retrofit2.http.GET;
    import retrofit2.http.Query;
    import rx.Observable;
    /**
    * Created by
    */
    public interface RetrofitApiService {
    @GET(“userinfo”)
    Observable<UserInfo> getUserInfo(@Query(“uid”) int uid);
    }
    复制代码
    这里就是把原生的retrofit中的Call换成了RxJava中的Observable.
    2、封装RetrofitUtil
    复制代码
    package com.xdw.retrofitrxmvpdemo.http;
    import android.content.Context;
    import com.google.gson.GsonBuilder;
    import com.xdw.retrofitrxmvpdemo.constant.UrlConstant;
    import okhttp3.OkHttpClient;
    import retrofit2.Retrofit;
    import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
    import retrofit2.converter.gson.GsonConverterFactory;
    /**
    * Created by 夏德旺 on 2017/12/8.
    */
    public class RetrofitUtil {
    private Context mCntext;
    //声明Retrofit对象
    private Retrofit mRetrofit;
    //声明RetrofitApiService对象
    private RetrofitApiService retrofitApiService;
    OkHttpClient client = new OkHttpClient();
    GsonConverterFactory factory = GsonConverterFactory.create(new GsonBuilder()。create());
    //达内android告诉我们,由于该对象会被频繁调用,采用单例模式,下面是一种线程安全模式的单例写法
    private volatile static RetrofitUtil instance;
    public static RetrofitUtil getInstance(Context context){
    if (instance == null) {
    synchronized (RetrofitUtil.class) {
    if (instance == null) {
    instance = new RetrofitUtil(context);
    }
    }
    }
    return instance;
    }
    private RetrofitUtil(Context mContext){
    mCntext = mContext;
    init();
    }
    //初始化Retrofit
    private void init() {
    mRetrofit = new Retrofit.Builder()
    .baseUrl(UrlConstant.BASE_URL)
    .client(client)
    .addConverterFactory(factory)
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .build();
    retrofitApiService = mRetrofit.create(RetrofitApiService.class);
    }
    public RetrofitApiService getRetrofitApiService(){
    return retrofitApiService;
    }
    }
    复制代码
    3、青岛android培训告诉我们,封装DataManager,这里和原生的retrofit的封装一样该类用来管理RetrofitApiService中对应的各种API接口,当做Retrofit和presenter中的桥梁,Activity就不用直接和retrofit打交道了
    复制代码
    package com.xdw.retrofitrxmvpdemo.manager;
    import android.content.Context;
    import com.xdw.retrofitrxmvpdemo.http.RetrofitApiService;
    import com.xdw.retrofitrxmvpdemo.http.RetrofitUtil;
    import com.xdw.retrofitrxmvpdemo.model.UserInfo;
    import rx.Observable;
    /**
    * Created by 夏德旺 on 2017/12/8.
    */
    //该类用来管理RetrofitApiService中对应的各种API接口,
    // 当做Retrofit和presenter中的桥梁,Activity就不用直接和retrofit打交道了
    public class DataManager {
    private RetrofitApiService mRetrofitService;
    private volatile static DataManager instance;
    private DataManager(Context context){
    this.mRetrofitService = RetrofitUtil.getInstance(context)。getRetrofitApiService();
    }
    //由于该对象会被频繁调用,采用单例模式,下面是一种线程安全模式的单例写法
    public static DataManager getInstance(Context context) {
    if (instance == null) {
    synchronized (DataManager.class) {
    if (instance == null) {
    instance = new DataManager(context);
    }
    }
    }
    return instance;
    }
    //将retrofit的业务方法映射到DataManager中,以后统一用该类来调用业务方法
    //青岛android培训班告诉我们,以后再retrofit中增加业务方法的时候,相应的这里也要添加,比如添加一个getOrder
    public Observable<UserInfo> getUserInfo(int uid){
    return mRetrofitService.getUserInfo(uid);
    }
    }
    复制代码
    4、青岛android培训机构告诉我们,创建一个Presenter接口,这里就引入了Presenter这个东西了,后面我们根据具体的业务创建对应的实例去实现该接口。该接口主要面向数据,后面还会创建一个PresentView接口(面向View的),然后通过
    BindPresentView方法将这2个接口关联起来,从而实现对数据和Activity的管理。
    复制代码
    package com.xdw.retrofitrxmvpdemo.presenter;
    import com.xdw.retrofitrxmvpdemo.pv.PresentView;
    /**
    * Created by 夏德旺 on 2017/12/8.
    */
    public interface Presenter {
    //Presenter初始化
    void onCreate();
    //销毁
    void onDestroy();
    //绑定视图
    void BindPresentView(PresentView presentView);
    }
    复制代码
    5、定义一个实现Presenter的基础类BasePresenter,后续具体功能类继承于它,主要是为了在该类中写一些共用方法,比如
    CompositeSubscription的创建与销毁。(CompositeSubscription干嘛用的可以查阅RxJava的资料)
    复制代码
    package com.xdw.retrofitrxmvpdemo.presenter;
    import com.xdw.retrofitrxmvpdemo.pv.PresentView;
    import rx.subscriptions.CompositeSubscription;
    /**
    * Created by 夏德旺 on 2017/12/8.
    */
    //定义一个Presenter的基础类,后续具体功能类继承于它
    public class BasePresenter implements Presenter {
    //声明一个CompositeSubscription对象,注意是protected修饰符,便于子类进行调用
    protected CompositeSubscription mCompositeSubscription;
    @Override
    public void onCreate() {
    //在基础类中对CompositeSubscription进行初始化,子类中就不用再写一次
    //子类如果需要对onCreate进行重写,记得先调用super.onCreate();
    mCompositeSubscription = new CompositeSubscription();
    }
    @Override
    public void onDestroy() {
    //释放CompositeSubscription,否则会造成内存泄漏
    if (mCompositeSubscription.hasSubscriptions()){
    mCompositeSubscription.unsubscribe();
    }
    }
    @Override
    public void BindPresentView(PresentView presentView) {
    //与具体视图进行绑定,留个子类进行扩展
    }
    }
    复制代码
    6、创建一个接口PresentView,面向视图View的接口,和前面的Prenseter配合使用
    复制代码
    package com.xdw.retrofitrxmvpdemo.pv;
    /**
    * Created by 夏德旺 on 2017/12/8.
    */
    //面向视图View的接口,和前面的Prenseter配合使用
    public interface PresentView {
    //定义一个最基础的接口,里面就包含一个出错信息的回调
    //因为大多数时候报错的时候都是采用一条信息提示
    //如果需要负责的报错接口,请重载onError,是重载不是重写
    void onError(String result);
    }
    复制代码
    7、之前还已经创建了2个类,这里补充下,一个是UrlConstant(用来存放常量的,这里用来存放Base Url),另外一个是数据模型类UserInfo
    UrlConstant.java:
    复制代码
    package com.xdw.retrofitrxmvpdemo.constant;
    /**
    * Created by 夏德旺 on 2017/12/8.
    */
    public class UrlConstant {
    /**
    * 域名:
    * 调试:http://10.1.1.192
    */
    public static final String BASE_URL=“http://10.1.1.192”;
    }
    复制代码
    UserInfo.java:
    复制代码
    package com.xdw.retrofitrxmvpdemo.model;
    /**
    * Created by 夏德旺 on 2017/12/8.
    */
    public class UserInfo {
    private String username;
    private int age;
    public UserInfo(String username, int age) {
    this.username = username;
    this.age = age;
    }
    public String getUsername() {
    return username;
    }
    public int getAge() {
    return age;
    }
    @Override
    public String toString() {
    return “UserInfo{” +
    “username=‘” + username + '\'' +
    “, age=” + age +
    '}';
    }
    }
    复制代码
    8、下面就需要将具体的业务加入到Presenter中了,先写一个UserInfoPv继承自PresentView接口,这个是根据具体业务添加。
    复制代码
    package com.xdw.retrofitrxmvpdemo.pv;
    import com.xdw.retrofitrxmvpdemo.model.UserInfo;
    /**
    * Created by 夏德旺 on 2017/12/8.
    */
    public interface UserInfoPv extends PresentView {
    //对基础接口PresentView进行扩展,添加onSuccess回调
    //因为该回调与具体的业务对应,所以不能写到基础接口里面
    //比如UserInfo的回调就创建一个UserInfoPv的接口,如果新增一个Order的业务,
    //则新增一个OrderPv的接口
    void onSuccess(UserInfo userInfo);
    }
    复制代码
    9、写一个UserInfoPresenter继承BasePresenter类,在该类中实现数据的请求,并且将该类与业务对应的PresentView进行绑定,这里是和UserInfoPv绑定
    复制代码
    package com.xdw.retrofitrxmvpdemo.presenter;
    import android.content.Context;
    import com.xdw.retrofitrxmvpdemo.manager.DataManager;
    import com.xdw.retrofitrxmvpdemo.model.UserInfo;
    import com.xdw.retrofitrxmvpdemo.pv.PresentView;
    import com.xdw.retrofitrxmvpdemo.pv.UserInfoPv;
    import rx.Observer;
    import rx.android.schedulers.AndroidSchedulers;
    import rx.schedulers.Schedulers;
    /**
    * Created by 夏德旺 on 2017/12/8.
    */
    //该类是具体业务presenter,如需增加另一个业务,比如Order
    //则可以再创建一个OrderPresenter
    public class UserInfoPresenter extends BasePresenter {
    private Context mContext;
    private UserInfoPv mUserInfoPv;
    private UserInfo mUserInfo;
    public UserInfoPresenter (Context context){
    this.mContext = context;
    }
    @Override
    public void BindPresentView(PresentView presentView) {
    mUserInfoPv = (UserInfoPv)presentView;
    }
    //在presenter中实现业务逻辑,此处会调用前面封装好的retrofit的东西
    //将处理结果绑定到对应的PresentView实例,这样Activity和PresentView实例绑定好之后,
    //Activity->PresentView->Presenter->retrofit的关系就打通了
    public void getUserInfo(int uid){
    super.mCompositeSubscription.add(DataManager.getInstance(mContext)。getUserInfo(uid)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<UserInfo>() {
    @Override
    public void onCompleted() {
    if (mUserInfo != null){
    mUserInfoPv.onSuccess(mUserInfo);
    }
    }
    @Override
    public void onError(Throwable e) {
    e.printStackTrace();
    mUserInfoPv.onError(“请求失败!!”);
    }
    @Override
    public void onNext(UserInfo userInfo) {
    mUserInfo = userInfo;
    }
    })
    );
    }
    }
    复制代码
    10、好了,retrofit与rxjava,presenter相关的东西都封装好了,接下来轮到之前苦逼的Activity出场了,在Activity中展示presenter传递过来的数据。
    复制代码
    package com.xdw.retrofitrxmvpdemo.activity;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;
    import com.xdw.retrofitrxmvpdemo.R;
    import com.xdw.retrofitrxmvpdemo.model.UserInfo;
    import com.xdw.retrofitrxmvpdemo.presenter.UserInfoPresenter;
    import com.xdw.retrofitrxmvpdemo.pv.UserInfoPv;
    public class MainActivity extends AppCompatActivity {
    private TextView text;
    private Button button;
    //定义需要调用的presenter对象
    private UserInfoPresenter mUserInfoPresenter =new UserInfoPresenter(this);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    text = (TextView)findViewById(R.id.text);
    button = (Button)findViewById(R.id.button);
    //在Activity创建的时候同时初始化presenter,这里onCreater不是指的创建presenter对象,
    // 而是做一些presenter的初始化操作,名字应该取名init更好理解点,我这里就不重命名了
    mUserInfoPresenter.onCreate();
    //将presenter和PresentView进行绑定,实际上就是将presenter和Activity视图绑定,
    //这个是MVP模式中V与P交互的关键
    mUserInfoPresenter.BindPresentView(mUserInfoPv);
    button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    //点击按钮触发presenter里面的方法
    mUserInfoPresenter.getUserInfo(1);
    }
    });
    }
    //采用内部类方法定义presentView对象,该对象用来将Activity和presenter进行绑定
    //绑定了以后主线程中就可以通过回调来获取网络请求的数据
    private UserInfoPv mUserInfoPv = new UserInfoPv(){
    @Override
    public void onSuccess(UserInfo userInfo) {
    text.setText(userInfo.toString());
    }
    @Override
    public void onError(String result) {
    Toast.makeText(MainActivity.this,result, Toast.LENGTH_SHORT)。show();
    }
    };
    //在Activity销毁的时候,一定要对CompositeSubscription进行释放,否则会造成内存泄漏
    //释放操作封装到了presenter的ondestroy方法中
    @Override
    protected void onDestroy(){
    super.onDestroy();
    mUserInfoPresenter.onDestroy();
    }
    }
    复制代码
    补充下:截图中的Result这个类是我实际项目中用到的,这里简化了下业务逻辑,就没用到它。
    Result.java:
    复制代码
    package com.xdw.retrofitrxmvpdemo.model;
    /**
    * Created by 夏德旺 on 2017/12/8.
    */
    public class Result<T> {
    private int code;
    private String msg;
    private T data;
    public Result(int code, String msg, T data) {
    this.code = code;
    this.msg = msg;
    this.data = data;
    }
    public int getCode() {
    return code;
    }
    public String getMsg() {
    return msg;
    }
    public T getData() {
    return data;
    }
    @Override
    public String toString() {
    return “Result{” +
    “code=” + code +
    “, msg=’” + msg + '\'' +
    “, data=” + data +
    '}';
    }
    }
    复制代码
    最后说明下,可能有的人觉得本来之前直接在Activity中写retrofit很方便,现在却加了这么多代码,视乎变得更麻烦了。但是自己仔细想想设计模式,当业务变得越来越复杂的时候,这种封装就会变得越来越有意义。
    希望对您有所帮助

更多山东android相关资讯,请扫描下方二维码

山东android
上一篇:山东android:Zxing二维码
下一篇:山东android:Glide加载图片

山东android:Handler消息传递

山东android:如何在android环境下实用http

山东android:Glide加载图片

山东android:网络请求框架搭建

选择城市和中心
贵州省

广西省

海南省

达内教育

有位老师想和您聊一聊