Retrofit2.0+rxjava2.0+rxlifecycle2基础使用(二)

接着Retrofit2.0基础使用(一),一般都是rxjava和retrofit最配吆,,,不过我见过的一般的项目都是retrofit2.0的项目,没有应用rxjava,最多就是项目基于mvp模式,外加dagger2就算是最高大上的了,所以研究rxjava2.0时候,有点绕路,自己研究了一下午,研究了一个皮毛,快速开发总算能用了。

为什么不说rxjava1.0的,有新的框架,谁还研究老框架啊,哈哈。研究及研究一下最热的框架,方能跟的上潮(zhaung)流(x)啊!

集成步骤基于Retrofit2.0基础使用(一)

使用步骤

一、在主工程可以引用的build.gradle中新增依赖

         //Rxjava  权限rxpermissions 使用到
        api 'io.reactivex.rxjava2:rxjava:2.2.5'
        api 'io.reactivex.rxjava2:rxandroid:2.1.0'
        api 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
        // rxLifecycle
        api 'com.trello.rxlifecycle2:rxlifecycle-android:2.0.1'
        api 'com.trello.rxlifecycle2:rxlifecycle-components:2.0.1'

说明:1.考虑网络加载中acitivity和fragment会退出的情况,而且同时存在多个请求的情况下,防止内存泄漏(甚至崩溃情况),需要在ondestroy中取消订阅事件,

           2.不想在baseAct或者baseFrt中定义一个map添加observe(或者Disposable),那样占用内存、而且逻辑判断复杂,还有是不是无网络请求的和有网络请求的分开呢,,

          3.听说过lifecy组件,没有使用过,开源的rxlifecycle2完全满足业务需求,不过rxlifecycle3集成报错,暂时使用主流稳定的的rxlifecycle2

 

二、单例的Retrofit和Okhttp管理类

    变化不大,只需要在buildRetrofit方法中得 new Retrofit.Builder()后面添加一句

 .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

 

三、创建 Callback的过滤类,为了适应各种网络状态和事件的统一处理,比如处理统一的错误状态、单点登录等等

       逻辑变化不大,就是更改了集成的父类名字,多了两个暂时不需要的方法(较真的话,可以使用,只是我暂时用不到)


import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import retrofit2.HttpException;

/**
 * @author hahaliu
 * @date 2019/1/15 0015
 * @annotate
 */
public abstract class RxCallBack<M extends BobyBean> implements Observer<M> {

    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onComplete() {

    }

    @Override
    public void onError(Throwable e) {
        e.printStackTrace();
        if (e instanceof HttpException) {
            HttpException httpException = (HttpException) e;
            int code = httpException.code();
            onFailed(code, "服务器升级中,请稍后重试");
            //Http状态码提示
            if (code >= 400 && code < 500) {
                LogUtils.e("请求错误");
            } else if (code >= 500) {
                LogUtils.e("服务器错误");
            }
        } else {
            onFailed(-100, "服务器升级中,请稍后重试");
        }
    }

    @Override
    public void onNext(M baseModel) {
        handleStatusCode(baseModel);
    }

    /**
     * 后台statuscode状态码处理,状态码类型封装在StatusCodeEnum中
     *
     * @param baseModel
     */
    private void handleStatusCode(M baseModel) {
        if (baseModel == null) {
            onFailed(-100, "服务器升级中,请稍后重试");
        } else {
            int statusCode = baseModel.code;
            switch (statusCode) {
                case 0:
                    onSucceed(baseModel);
                    break;
                default:
                    onFailed(statusCode, baseModel.msg);
                    break;
            }
        }
    }


    public abstract void onSucceed(M response);

    public abstract void onFailed(int errorCode, String msg);
}

其中 其中错误状态没有变化,bean类和logUtils自行脑补

 

四、请求声明


import java.util.Map;

import io.reactivex.Observable;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.PartMap;
import retrofit2.http.Query;
import retrofit2.http.Url;

/**
 * @author hahaliu
 * @date 2019/1/8 0008
 * @annotate
 */
public interface RemoteRealService {

    /**
     * 登录
     * @param username
     * @param password
     * @param clientType
     * @return
     */
    @POST("login")
    Observable<BobyBean<UserBean>> login(@Query("username") String username, @Query("password") String password, @Query("clientType") String clientType);


    /**
     * 单个文件上传
     * @param tableName
     * @param file
     * @return
     */
    @Multipart
    @POST("fjwj/fileUpload")
    Call<BobyBean<FileBean>> fjwj_fileUpload_only_retrofit(@Part("tableName") RequestBody tableName, @Part MultipartBody.Part file);

    /**
     * 多文件上传
     * @param tableName
     * @param params
     * @return
     */
    @Multipart
    @POST("fjwj/fileUpload")
    Observable<BobyBean<FileBean>> fjwj_fileUpload_retrofit(@Part("tableName") RequestBody tableName, @PartMap Map<String, RequestBody> params);

    /**
     * 文件下载
     * @param url
     * @return
     */
    @GET
    Observable<ResponseBody> loadFile(@Url String url);
}

Call换为Observable而已

 

import com.trello.rxlifecycle2.LifecycleProvider;
import com.trello.rxlifecycle2.android.ActivityEvent;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;

/**
 * @author hahaliu
 * @ClassName Http
 * @Description 所有接口统一
 * @date 2018-09-20
 */
public class Http implements IRemoteService {


    /**
     * 统一设置Observable
     *
     * @param observable
     * @param <T>
     * @return
     */
    public static <T> Observable<T> observe(Observable<T> observable) {
        return observable
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

  /**
     * rxjava +retrofit 请求方式
     *
     * @param username
     * @param password
     * @param callback
     */
    public static void doLogin(LifecycleProvider activity, String username, String password, final RxCallBack<BobyBean<UserBean>> callback) {
        RemoteRealService service = HttpsClientUtil.newInstance().create(RemoteRealService.class);
        Observable<BobyBean<UserBean>> observable = observe(service.login(username, password, "app"));
        observable
                .compose(activity.<BobyBean<UserBean>>bindUntilEvent(ActivityEvent.DESTROY))
                .subscribe(callback);
    }

/**
     * 单文件上传  retrofit
     *
     * @param tableName
     * @param file
     * @param callback
     */
    public static void fjwj_fileUpload_only_retrofit(LifecycleProvider activity,String tableName, File file, RxCallBack<BobyBean<FileBean>> callback) {
        RemoteRealService service = HttpsClientUtil.newInstance().create(RemoteRealService.class);

        RequestBody tableBoay = RequestBody.create(MediaType.parse("text/plain"), tableName);

        RequestBody photoRequestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
        MultipartBody.Part photo = MultipartBody.Part.createFormData("file", file.getName(), photoRequestBody);

        Observable<BobyBean<FileBean>> observable = service.fjwj_fileUpload_only_retrofit(tableBoay, photo);
        observable
                .compose(activity.<BobyBean<FileBean>>bindUntilEvent(ActivityEvent.DESTROY))
                .subscribe(callback);
    }

    /**
     * 多文件统一上传 retrofit
     *
     * @param tableName
     * @param files
     * @param callback
     */
    public static void fjwj_fileUpload_retrofit(LifecycleProvider activity, String tableName, List<File> files, RxCallBack<BobyBean<FileBean>> callback) {
        RemoteRealService service = HttpsClientUtil.newInstance().create(RemoteRealService.class);

        RequestBody tableBoay = RequestBody.create(MediaType.parse("text/plain"), tableName);

        Map<String, RequestBody> params = new HashMap<>();
        for (File file : files) {
            RequestBody photoRequestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
            params.put("file\"; filename=\"" + file.getName(), photoRequestBody);

        }
        Observable<BobyBean<FileBean>> observable = observe(service.fjwj_fileUpload_retrofit(tableBoay, params));
        observable
                .compose(activity.<BobyBean<FileBean>>bindUntilEvent(ActivityEvent.DESTROY))
                .subscribe(callback);
    }

 /**
     * 文件下载
     *
     * @param context
     * @param url
     * @param fileDes  文件夹存储的命名
     * @param position 回调状态--本方法中为文件列表的下表
     * @param listener 自定义的回调监听 方法onItemClickListener的两个int类型参数 type事件类型 position回调状态
     */
    public static void loadFile(final LifecycleProvider provider, final Context context, String url, final String fileDes, final int position, final BaseRecyclerBottomSpaceAdapter.OnItemCommonClickListener listener) {
        RemoteRealService service = HttpsClientUtil.newInstance().create(RemoteRealService.class);
        Observable<ResponseBody> call = observe(service.loadFile(url));
        call.compose(provider.<ResponseBody>bindUntilEvent(ActivityEvent.DESTROY))
                .subscribe(new Observer<ResponseBody>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                    }

                    @Override
                    public void onNext(ResponseBody responseBody) {
                        if (responseBody != null) {
                            boolean writeToDisk = Http.writeFileToSDCard(context, fileDes, responseBody);
                            if (writeToDisk) {
                                AppConfig.openFile(context, new File(AppConfig.getAppCacheFilePath(context), fileDes));
                                listener.onItemClickListener(1, position);
                            } else {
                                listener.onItemClickListener(-1, -1);
                            }
                        } else {
                            listener.onItemClickListener(-1, -1);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        listener.onItemClickListener(-1, -1);
                    }

                    @Override
                    public void onComplete() {
                    }
                });
    }

  

    /**
     * 下载文件
     *
     * @param context
     * @param fileDes 文件路径
     * @param body
     * @return
     */
    private static boolean writeFileToSDCard(Context context, String fileDes, ResponseBody body) {
        try {
            File futureStudioIconFile = new File(AppConfig.getAppCacheFilePath(context), fileDes);
            InputStream inputStream = null;
            OutputStream outputStream = null;
            try {
                byte[] fileReader = new byte[4096];
                long fileSize = body.contentLength();
                long fileSizeDownloaded = 0;
                inputStream = body.byteStream();
                outputStream = new FileOutputStream(futureStudioIconFile);
                while (true) {
                    int read = inputStream.read(fileReader);
                    if (read == -1) {
                        break;
                    }
                    outputStream.write(fileReader, 0, read);
                    fileSizeDownloaded += read;
                    Log.d("", "file download: " + fileSizeDownloaded + " of " + fileSize);
                }
                outputStream.flush();
                return true;
            } catch (IOException e) {
                return false;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            }
        } catch (IOException e) {
            return false;
        }
    }
}

注意:1.baseActivity和baseFragment分别继承RxAppCompatActivity、RxFragment

           2..compose(activity.<BobyBean<FileBean>>bindUntilEvent(ActivityEvent.DESTROY))参数值写死了,如果有act和fra两种情况,应该使用参数传递形势赋值。

 

参考资料:https://www.jianshu.com/p/0ad99e598dba

rxjava是个好东西,rxJava2.0还需要很多坑要填,所以日后就是项目的标配了,先记录一下入门大法:

https://www.jianshu.com/p/464fa025229e

https://www.jianshu.com/p/b39afa92807e

https://www.jianshu.com/p/0cd258eecf60

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值