近日老出现尴尬的事儿,自己写的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 getData(@Url String url);
/**
* @param url 请求子地址
* @param params 请求参数
* @return Retrofit2 的Observable对象
*/
@FormUrlEncoded
@POST()
Observable postData(@Url String url, @FieldMap(encoded = true) Map params);
/**
* 图片上传
* @param url 请求子地址
* @param partMap 请求参数
* @param paramfile 上传的file文件
* @return Retrofit2 的Observable对象
*/
@Multipart
@POST()
Observable uploadImg(@Url String url, @PartMap() Map 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 postData(String url, HashMap params) {
Observable 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 {
private CommonModel model;
public CommonPresenter() {
model = new CommonModel();
}
@Override
public void postData(final BaseActivity activity, String url,
HashMap 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
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>
implements IBaseView, IBase {
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 {
@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 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) {
}
}
}
差不多了,看了下还算能看懂,就这吧