【Android】Retrolfit2+Rxjava2 + OkHttp請求網絡+取消已發出網絡請求

 

    近日老出現尷尬的事兒,自己寫的app自己測試時遇不到的問題總是在同事要看時出現,像中了魔咒一樣,於是下定決心,一定要搞了她,於是開始瘋狂點擊,不出所料出現了,NPE了,看了下原來是一個Butterknife註解的RecyclerView在調用時報的,具體原因是,進入一個頁面進行了網絡請求,在結果還沒返回時就退出了該界面,但是好死不死的是界面沒完全銷燬時結果出來了,這個時候這個RecyclerView已經被銷燬了,所以再在success方法中調用RecyclerView去操作時就會報NPE.

    這裏記錄一下Retrolfit2+Rxjava2 + Okhttp的使用及對上述問題的處理辦法。

 

 0、首先封裝Retrolfit

import com.nxt.harmlessmanagesys.constant.SwitchConstant;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * @author: LiuChaoya
 * @createTime: 2018/4/10 0010 14:45
 * @classDescription: 封裝Retrolfit
 * @email: [email protected]
 */

public enum RetrofitClient {
    INSTANCE;

    private static String BASEURL = API.BASEURL;
    public RetrofitServicer getService() {
        return new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(BASEURL)
                .client(createOkhttpClient())
                .build()
                .create(RetrofitServicer.class);
    }

    private Boolean OKHTTP_LOG = SwitchConstant.NetRequestSet.OKHTTP_LOG;
    private HttpLoggingInterceptor.Level OKHTTP_LOG_LEVEL = SwitchConstant.NetRequestSet.OKHTTP_LOG_LEVEL;
    private Integer CONNECT_TIME_OUT = SwitchConstant.NetRequestSet.CONNECT_TIME_OUT;
    private Integer WRITE_TIME_OUT = SwitchConstant.NetRequestSet.WRITE_TIME_OUT;
    private Integer READ_TIME_OUT = SwitchConstant.NetRequestSet.READ_TIME_OUT;

    private OkHttpClient createOkhttpClient() {
        OkHttpClient.Builder okhttpBuilder = new OkHttpClient.Builder();
        if (OKHTTP_LOG) {
            okhttpBuilder.addNetworkInterceptor(
                    new HttpLoggingInterceptor().setLevel(OKHTTP_LOG_LEVEL));
        }
        if (CONNECT_TIME_OUT != null) {
            okhttpBuilder.connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS);
        }
        if (WRITE_TIME_OUT != null) {
            okhttpBuilder.writeTimeout(WRITE_TIME_OUT, TimeUnit.SECONDS);
        }
        if (READ_TIME_OUT != null) {
            okhttpBuilder.readTimeout(READ_TIME_OUT, TimeUnit.SECONDS);
        }
        return okhttpBuilder.build();
    }
}

 

1、service類構建

import java.util.Map;

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

/**
 * @author: LiuChaoya
 * @createTime: 2018/4/10 0010 14:50
 * @classDescription: service
 * @email: [email protected]
 */

public interface RetrofitServicer {

    /**
     * @param url      請求子地址
     * @return         Retrofit2 的Observable對象
     */
    @GET
    Observable<ResponseBody> getData(@Url String url);

    /**
     * @param url       請求子地址
     * @param params   請求參數
     * @return          Retrofit2 的Observable對象
     */
    @FormUrlEncoded
    @POST()
    Observable<ResponseBody> postData(@Url String url, @FieldMap(encoded = true) Map<String, Object> params);

    /**
     * 圖片上傳
     * @param url        請求子地址
     * @param partMap   請求參數
     * @param paramfile      上傳的file文件
     * @return           Retrofit2 的Observable對象
     */
    @Multipart
    @POST()
    Observable<ResponseBody> uploadImg(@Url String url, @PartMap() Map<String, RequestBody> partMap, @Part MultipartBody.Part paramfile);
}


2、model創建

import com.nxt.harmlessmanagesys.module.contract.Contract;
import com.nxt.harmlessmanagesys.module.data.net.RetrofitClient;
import com.nxt.harmlessmanagesys.utils.gson.GsonUtil;
import com.orhanobut.logger.Logger;

import java.util.HashMap;

import io.reactivex.Observable;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;

/**
 * @author: LiuChaoya
 * @createTime: 2018/4/10 0010 14:55
 * @classDescription: 
 * @email: [email protected]
 */

public class CommonModel implements Contract.Model {

    @Override
    public Observable<ResponseBody> postData(String url, HashMap<String, Object> params) {
        Observable<ResponseBody> data = RetrofitClient.INSTANCE.getService().postData(url, params);
        Logger.d("網路請求參數↓↓↓(請求地址==>" + url + "<==)");
        Logger.json(GsonUtil.INSTANCE.objectToString(params));
        return data;
    }
}
Contract是一個契約類,自己隨便寫寫就出來了,這裏也僅僅示範一個post請求的調用

3、presenter創建

import com.nxt.harmlessmanagesys.R;
import com.nxt.harmlessmanagesys.base.BaseActivity;
import com.nxt.harmlessmanagesys.base.BasePresenter;
import com.nxt.harmlessmanagesys.base.IBaseView;
import com.nxt.harmlessmanagesys.module.data.net.CustomObserver;
import com.nxt.harmlessmanagesys.module.model.CommonModel;
import com.orhanobut.logger.Logger;

import java.util.HashMap;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;

/**
 * @author: LiuChaoya
 * @createTime: 2018/4/10 0010 14:58
 * @classDescription: 常用的presenter
 * @email: [email protected]
 */

public class CommonPresenter extends BasePresenter<IBaseView,Disposable> {

    private CommonModel model;

    public CommonPresenter() {
        model = new CommonModel();
    }


    @Override
    public void postData(final BaseActivity activity, String url,
                         HashMap<String, Object> params, final int type, String tip) {
        if (mView != null && !checkNet(activity)) {
            mView.showNoNet();
            return;
        }
        activity.showProgressDialog(tip);
        model.postData(url, params)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new CustomObserver() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        super.onSubscribe(d);
                        disposables.add(d);
                        //發起請求後將本次請求返回的Disposable對象保存,用於取消網絡請求用,            
                        //CompositeDisposable對象在父類BasePresenter
                    }
 
                    @Override 
                    public void onSuccess(String s) { 
                        //網絡請求成功的處理邏輯 
                    }

                    @Override 
                    public void mOnError(String msg, String code) { 
                        //網絡請求失敗的處理邏輯 
                    } 
        }); 
    }
} 

} @Override public void onSuccess(String s) { //網絡請求成功的處理邏輯 } @Override public void mOnError(String msg, String code) { //網絡請求失敗的處理邏輯 } }); }}    父presenter

import android.content.Context;

import com.nxt.harmlessmanagesys.module.contract.Contract;
import com.nxt.harmlessmanagesys.utils.NetworkTool;

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

import io.reactivex.disposables.Disposable;

/**
 * @author: LiuChaoya
 * @createTime: 2018/4/10 0010 15:07
 * @classDescription: 
 * @email: [email protected]
 */
public abstract class BasePresenter<T extends IBaseView implements Contract.Presenter {
    protected T mView;
    protected CompositeDisposable disposables = new CompositeDisposable();

    void attach(T mView) {
        this.mView = mView;
    }

    void detachView() {
        if (mView != null) {
            mView = null;
        }
    }

    protected boolean checkNet(Context context){
        return NetworkTool.isNetWorkConnected(context);
    }

    /**
     * 頁面銷燬時取消所有網絡請求
     */
    void cancelAllRequest() {
        disposables.clear();
    }


4、activity中調用

import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.nxt.harmlessmanagesys.R;
import com.nxt.harmlessmanagesys.utils.ContextUtils;
import com.nxt.harmlessmanagesys.utils.DialogTools;
import com.nxt.harmlessmanagesys.utils.SPUtil;
import com.nxt.harmlessmanagesys.utils.gson.GsonUtil;
import com.nxt.harmlessmanagesys.widght.CustomDialog;
import com.nxt.harmlessmanagesys.widght.ImageCircleView;
import com.umeng.analytics.MobclickAgent;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import butterknife.ButterKnife;
import butterknife.Unbinder;
import io.reactivex.disposables.Disposable;

/**
 * @author: LiuChaoya
 * @createTime: 2018/4/10 0010 15:10
 * @classDescription: activity基類
 * @email: [email protected]
 */

public abstract class BaseActivity<T extends BasePresenter<IBaseView,Disposable>> 
        implements IBaseView, IBase<T> {

    private View mRootView;
    protected T mPresenter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

        mPresenter = getPresenter();//子類實現

        if (mPresenter != null) {
            mPresenter.attach(this);
        }
        mRootView = createView(null, null, savedInstanceState);//初始化佈局 和 ButterKnife
        setContentView(mRootView);
        unbinder = ButterKnife.bind(this, mRootView);
        myBindView(savedInstanceState);//在子類實現
    }

    @Override
    public View createView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return ContextUtils.inflate(this, getContentLayout());//getContentLayout()在子類實現
    }

    @Override
    public View getView() {
        return mRootView;
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (unbinder != null) {
            unbinder.unbind();//解綁
        }
        if (mPresenter != null) {
            mPresenter.detachView();//銷燬view
            mPresenter.cancelAllRequest();//取消網絡請求
        }
    }
}

 


5、示例子類activity

 

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

import com.luck.picture.lib.tools.DoubleUtils;
import com.nxt.harmlessmanagesys.R;
import com.nxt.harmlessmanagesys.base.BaseListActivity;
import com.nxt.harmlessmanagesys.base.BaseRecyclerAdapter;
import com.nxt.harmlessmanagesys.module.data.net.API;
import com.nxt.harmlessmanagesys.module.entity.ReportListBean;
import com.nxt.harmlessmanagesys.module.presenter.CommonPresenter;
import com.nxt.harmlessmanagesys.module.views.supervisecenter.holder.SceneCollectHolder;
import com.nxt.harmlessmanagesys.utils.SPUtil;
import com.nxt.harmlessmanagesys.utils.gson.GsonUtil;

import java.util.ArrayList;

/**
 * @author: LiuChaoya
 * @createTime: 2018/3/30 0030 11:02
 * @classDescription: 監管中心--現場收集
 * @email: [email protected]
 */

public class SceneCollectActivity extends BaseListActivity<CommonPresenter> {

    @Override
    public CommonPresenter getPresenter() {
        return new CommonPresenter();
    }

    @Override
    public int getContentLayout() {
        return R.layout.activity_list;
    }


    @Override
    public void myBindView(Bundle savedInstanceState) {
        getList("get");
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == SAVE_DETAIL && resultCode == RESULT_OK){
            // TODO: LiuChaoya 2018/4/9 0009 9:13 保存詳情回來,要麼數據帶回來整合,要麼刷新列表

        }
    }


    protected void getList(String tip) {
        HashMap<String, Object> mMapParams = new HashMap<>();
        mMapParams.clear();
        mMapParams.put("api_method", "c.findReportList");
        mMapParams.put("a_id", SPUtil.getUSERID());
        mPresenter.postData(this, API.REPORT_LIST, mMapParams, NET_INDEX_ONE, tip);
    }

    @Override
    public void showSuccess(String s, int type) {
        if (type == NET_INDEX_ONE) {
            
        }
    }
}


差不多了,看了下還算能看懂,就這吧

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章