這一片博文 主要着眼于mvp架構和retrofit+rxjava的配合;以一個簡單執行個體來實作使用者的登入;
首先來看效果圖:
重要的是功能,界面較為簡單:
1.Mvp 實作login的總體架構
2.網絡請求為 retrofit ,實作多層次封裝
3.retrofit的請求和響應使用 rxjava 來實作
在看代碼之前首先來看項目的整體架構:
作為業務邏輯和業務模型的model層 不僅僅可以放置javabean 部分業務邏輯接口可以放在這裡 一個人而定
ok~ 下面 以代碼為主導線開始剖析:
1.model層:
僅展示loginInfo代碼 不做解釋:
package com.example.houruixiang.mvp.model;
/**
* Created by houruixiang on 2017/8/28.
*/
public class LoginInfo {
private int errorcode;
private String message;
private DataBean data;
public int getErrorcode() {
return errorcode;
}
public void setErrorcode(int errorcode) {
this.errorcode = errorcode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public class DataBean {
private String flag;
private String stuname;
private String tel;
private String stuid;
private String photo;
private String idcard;
private String sex;
private String registered;
private String address;
private String km;
private String signname;
private String cartype;
private String pinscode;
private String zylx;
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
public String getStuname() {
return stuname;
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getStuid() {
return stuid;
}
public void setStuid(String stuid) {
this.stuid = stuid;
}
public String getPhoto() {
return photo;
}
public void setPhoto(String photo) {
this.photo = photo;
}
public String getIdcard() {
return idcard;
}
public void setIdcard(String idcard) {
this.idcard = idcard;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getRegistered() {
return registered;
}
public void setRegistered(String registered) {
this.registered = registered;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getKm() {
return km;
}
public void setKm(String km) {
this.km = km;
}
public String getSignname() {
return signname;
}
public void setSignname(String signname) {
this.signname = signname;
}
public String getCartype() {
return cartype;
}
public void setCartype(String cartype) {
this.cartype = cartype;
}
public String getPinscode() {
return pinscode;
}
public void setPinscode(String pinscode) {
this.pinscode = pinscode;
}
public String getZylx() {
return zylx;
}
public void setZylx(String zylx) {
this.zylx = zylx;
}
}
}
然後再這裡 順便定義了一個請求的接口:
(作為對retrofit 請求的二次封裝的)
public interface RequestListener<T>{
void onSuccess(Response<T> response);
void onFail(Throwable t);
}
使用場景
比如:
// call.enqueue(new Callback<T>() {
// @Override
// public void onResponse(Call<T> call, retrofit2.Response<T> response) {
// mListener.onSuccess(response);
// }
//
// @Override
// public void onFailure(Call<T> call, Throwable t) {
// mListener.onFail(t);
// }
// });
在這裡我們用rxjava在封裝請求的響應暫時不用它;
2.presenter層:
presenter作為連接配接view和model的跳闆在建立時候 最好先在其中建立一個總得接口IPresenter來定義方法 :
1. 管理字段屬性的擷取(比如登入需要使用者名密碼的存儲等);
2. 請求成功失敗之後的互動;
3. 還有隊一些互動的處理(如加載框等)
那麼來看IPresenter:
public interface IPresenter {
//想要得到什麼
//請求完的互動
void onMainActiviy();
void onFailToast();
//互動的load設定
void showLoad();
void hideLoad();
}
接着看ApiClient,完成對retrofit的初始化和請求的初步封裝:
1.初始化retrofit類和代理類:
private ApiClient() {
init();
//建立retrofit
//設定請求OkhhtpClient執行個體
mRetrofit = new Retrofit.Builder()
.baseUrl("....")
.client(mOkhttpClient) //設定請求OkhhtpClient執行個體
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
public <T> T create(Class<T> service){
T t = mRetrofit.create(service);
return t;
}
然後 初始化攔截器(讀取和延時時間等):
public void init(){
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
//添加攔截器
if (builder.interceptors() != null){
builder.interceptors().clear();
}
builder
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// 關于請求的列印日志
// String path = request.url().encodedFragment();
// String query = request.url().query();
return chain.proceed(request);
}
}).connectTimeout(, TimeUnit.SECONDS)
.readTimeout(,TimeUnit.SECONDS)
.writeTimeout(,TimeUnit.SECONDS);
mOkhttpClient = builder.build();
}
最後是對請求的初步封裝 這裡我們用到rxjava:
public <T> void onLoad(Observable<T> call, Subscriber<T> subscriber){
// call.enqueue(new Callback<T>() {
// @Override
// public void onResponse(Call<T> call, retrofit2.Response<T> response) {
// mListener.onSuccess(response);
// }
//
// @Override
// public void onFailure(Call<T> call, Throwable t) {
// mListener.onFail(t);
// }
// });
call.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
}
由于retrofit提供了兩套API是以rxjava 用起來比較友善;注意:注釋部分為原始API下的封裝;正文為rxjava的封裝
接下來是注解API 的建構:
@FormUrlEncoded
@POST("/api/TimApi")
Observable<LoginInfo> getInfo(@Field("name")String name, @Field("key")String key,@Field("code")String code, @Field("data")String data);
}
然後在basePresenter中完成IPresenter ApiClient Retrofit-Service的初始化
public class BasePresenter {
public IPresenter mIp;
public ApiClient mApi;
public ReponseInfoApi mService;
public BasePresenter(IPresenter iPresenter) {
mApi = ApiClient.getInstance();
mIp = iPresenter;
mService = mApi.create(ReponseInfoApi.class);
}
public void load(String code,String data){
mIp.showLoad();
}
}
最後建立直接調用的LoginPresenter:
// @Override
// public void load(String code, String data) {
// super.load(code, data);
// Call<LoginInfo> info = mService.getInfo("APPAPI", "123456", code, data);
//
//
//
// mApi.onLoad(info, new RequestListener<LoginInfo>() {
// @Override
// public void onSuccess(Response<LoginInfo> response) {
// mIp.hideLoad();
// LoginInfo.DataBean dataBean = response.body().getData();
// String flag = dataBean.getFlag();
// if (flag.equals("1")){
//
// mIp.onMainActiviy();
// }else {
// mIp.onFailToast();
// }
// }
//
// @Override
// public void onFail(Throwable t) {
// mIp.hideLoad();
// mIp.onFailToast();
// }
// });
//
//
// }
@Override
public void load(String code, String data) {
super.load(code, data);
Observable<LoginInfo> info = mService.getInfo("APPAPI", "123456", code, data);
mApi.onLoad(info, new Subscriber<LoginInfo>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
mIp.hideLoad();
mIp.onFailToast();
}
@Override
public void onNext(LoginInfo loginInfo) {
mIp.hideLoad();
LoginInfo.DataBean dataBean = loginInfo.getData();
String flag = dataBean.getFlag();
if (flag.equals("1")){
mIp.onMainActiviy();
}else {
mIp.onFailToast();
}
}
});
}
注意 注解為正常Api下的二次封裝 正文為rxjava的請求響應封裝;
2.View層:
先來看下activity的代碼:
public class MainActivity extends AppCompatActivity implements IPresenter, View.OnClickListener {
private LoginPresenter mPresenter;
private TextView mUsername;
private TextView mPwd;
private Button mLogin;
private ImageView mLoad;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPresenter = new LoginPresenter(this);
initView();
initEvent();
}
private void initView() {
mUsername = (TextView) findViewById(R.id.username);
mPwd = (TextView) findViewById(R.id.pwd);
mLogin = (Button) findViewById(R.id.login);
mLoad = (ImageView) findViewById(R.id.load);
}
private void initEvent() {
mLogin.setOnClickListener(this);
}
@Override
public void onClick(View view) {
String user = mUsername.getText().toString().trim();
String pwd = mPwd.getText().toString().trim();
if (user == null || user.equals("") || pwd == null || pwd.equals("")){
return;
}
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("tel",user);
jsonObject.put("pwd",pwd);
jsonObject.put("pname","北京");
} catch (JSONException e) {
e.printStackTrace();
}
String data = jsonObject.toString().replaceAll("\"(\\w+)\"(\\s*:\\s*)", "$1$2");
mPresenter.load("1001",data);
}
@Override
public void onMainActiviy() {
Toast.makeText(this,"success",Toast.LENGTH_SHORT).show();
}
@Override
public void onFailToast() {
Toast.makeText(this,"fail",Toast.LENGTH_SHORT).show();
}
@Override
public void showLoad() {
mLoad.setVisibility(View.VISIBLE);
}
@Override
public void hideLoad() {
mLoad.setVisibility(View.GONE);
}
}
作為mvp中隻進行布局的activity 首先實作IPresenter 實作互動的方法和加載框的方法 然後在點選事件中自身作為參數來初始化LoginPresenter,在LoginPresenter中請求成功時候調用activity中提前定義好的hideLoad()和互動方法onMainActiviy();當請求失敗時候調用hideLoad()和onFailToast();
這樣一個簡單的MVP+Retrofit+Rxjava就實作了 在之後 會主要交接下Rxjava ~
謝謝 閱讀