最近刚接触RxJava,结合Retrofit在加上MVP模式来实现网络请求。代码是技术的一种实现,但更重要的是思想。Retrofit是基于Okhttp封装的用于网络请求的框架,RxJava与RxAndroid结合使得Android的异步操作更加优雅,易于维护。接下来通过实现一个用户的登陆功能,接收服务端返回的数据,来判断是否登陆成功。下面简要说明一下我的思路:,
一、.添加依赖的各种库。
二、创建接收网络返回的实体类,用于解析网络请求结果。
三、根据返回数据类型,创建网络请求接口,通过RxJava的Observable(被观察者)处理网络返回数据,创建网络请求功能。
四、创建MVP模式,分别处理不同层面的逻辑功能,即通过接口来实现数据从 V —》P—》M —》服务器,在将数据从服务器—》M—》P—》V的传递。
第3、4步才是核心部分。下面依次来实现一下
一、添加依赖的各种库
//retrofit 系列库
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
//retrofit默认回调的适配器
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
//gson转换器 convert Gson
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
//Rxjava2 系列库
//Rxandroid
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
//RxJava 使用Rxjava2需要依赖的库
implementation 'io.reactivex.rxjava2:rxjava:2.2.3'
二、创建接收网络返回的实体类,用于解析网络请求结果。
创建接收数据的实体类LoginResult.ava
public class LoginResult {
/*String aa = "data : {\"token\":\"eyJ1c2VybmFtZSI6ICJ4dXNodW4iLCAiZXhwIjogIjIwMTctMDctMjMgMDY6NTc6MTIifQ==\"}";*/
private int success;
private String msg;
private DataBean dataBean;
public int getSuccess() {
return success;
}
public void setSuccess(int success) {
this.success = success;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public DataBean getDataBean() {
return dataBean;
}
public void setDataBean(DataBean dataBean) {
this.dataBean = dataBean;
}
public class DataBean{
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
}
三、 根据返回数据类型,创建网络请求接口
1.此处才是将RxJava与Retrofit关联起来的关键。见ApiInterfaceService.java
/**
* Author : Zmj
* Blog : https://blog.csdn.net/Zmj_Dns
* DitHub : https://github.com/ZmjDns
* Time : 2019/1/24
* Description :用于请求网络的接口
*/
public interface ApiInterfaceService {
@POST("?action=login")
@FormUrlEncoded
Observable<LoginResult> loginByObservablePost(@FieldMap Map<String, RequestBody> paramsBody);
//网络请求作为被观察者,用Observable来声明
}
2.创建Retrofit网络请求单例,见RetrofitClientSingleton.java
/**
* Author : Zmj
* Blog : https://blog.csdn.net/Zmj_Dns
* DitHub : https://github.com/ZmjDns
* Time : 2019/1/24
* Description :Retrofit封装类 单例模式
*/
public class RetrofitClientSingleton {
private final String TAG = this.getClass().getSimpleName();
private static RetrofitClientSingleton retrofitInstance;
private static final int TIME_OUT = 20;
private static final String BASR_URL = "http://192.168.1.254:8080/myssm/";
private Retrofit myRertofit;
public final ApiInterfaceService myApiService;
public static RetrofitClientSingleton getInstance() {
if (retrofitInstance == null){
synchronized (RetrofitClientSingleton.class){
if (retrofitInstance == null){
retrofitInstance = new RetrofitClientSingleton();
}
}
}
return retrofitInstance;
}
private RetrofitClientSingleton() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(TIME_OUT, TimeUnit.SECONDS);
myRertofit = new Retrofit.Builder()
.baseUrl(BASR_URL) //基础URL
.client(builder.build()) //配置OkHttp的配置
.addConverterFactory(GsonConverterFactory.create()) //数据转换
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) //网络请求适配
.build();
//获取APiService对象,用于请求网络
myApiService = myRertofit.create(ApiInterfaceService.class);
}
}
四、MVP模式实现
1.创建View接口,用于Vie与Presenter数据传递,见IView.java
public interface IView {
void showLoading();
//用于显示数据
void showData(LoginResult result);
}
2.创建Model接口,用于Model与Presenter之间数据传递,见IModel.java
public interface IModel {
//被观察者,此处引入RxJava的被观察者
Observable<LoginResult> login(String name,String psd,Observer<LoginResult> observer);
}
3. Model实现IModel,进行网络请求,见LoginModel.java
/**
* Author : Zmj
* Blog : https://blog.csdn.net/Zmj_Dns
* DitHub : https://github.com/ZmjDns
* Time : 2019/1/24
* Description :
*/
public class LoginModel implements IModel {
private final String TAG = this.getClass().getSimpleName();
@Override
public Observable<LoginResult> login(String name, String psd,Observer<LoginResult> observer) {
//对View曾传来的数据处理
Map<String, RequestBody> paramsBody = new HashMap<>();
RequestBody rbname = RequestBody.create(MediaType.parse("text/plain"),name);
RequestBody rbPsd = RequestBody.create(MediaType.parse("text/plain"),psd);
paramsBody.put("name",rbname);
paramsBody.put("password",rbPsd);
//被观察者执行网络请求
return Observable.create(new ObservableOnSubscribe<LoginResult>() {
@Override
public void subscribe(ObservableEmitter<LoginResult> emitter) throws Exception {
//获取ApiInterfaceService对象
RetrofitClientSingleton.getInstance().myApiService.loginByObservablePost(paramsBody)
.subscribeOn(Schedulers.io()) //在子线程中网络请求
.observeOn(AndroidSchedulers.mainThread())//在主线程中操作返回结果
.subscribe(observer); //将observable(被观察者)与observer(观察者)关联
}
});
}
}
4.实现prenster,调度整体逻辑,见LoginPersenter.java
/**
* Author : Zmj
* Blog : https://blog.csdn.net/Zmj_Dns
* DitHub : https://github.com/ZmjDns
* Time : 2019/1/24
* Description :
*/
public class LoginPersenter<T extends IView> {
private final String TAG = this.getClass().getSimpleName();
//用于持有View的弱引用
private WeakReference<T> weakReference;
private LoginModel loginModel = new LoginModel();
public LoginPersenter() {
}
public void onAttach(T view){
weakReference = new WeakReference<>(view);
}
public void detach(){
weakReference.clear();
}
/**
* 此方法是关键,在View层调用此方法,就完成的数据在不同层之间的传递
* @param name
* @param psd
*/
public void login(String name, String psd){
if (weakReference.get() != null){
weakReference.get().showLoading();//UI操作
if (loginModel != null){
//此处实现观察者的功能,用于处理网络返回数据
Observer<LoginResult> observer = new Observer<LoginResult>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe: INLOGINPRESENTER");
}
@Override
public void onNext(LoginResult result) {
//获取数据在UI操作
weakReference.get().showData(result);
Log.d(TAG, "onNext: INLOGINPRESENTER" + result.getDataBean().getToken());
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: INLOGINPRESENTER" + e.getMessage());
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete: INLOGINPRESENTER");
}
};
//获取Model层请求网络结果的被观察者对象
Observable<LoginResult> observable = loginModel.login(name,psd,observer);
//将observable(被观察者)与observer(观察者)关联
observable.subscribe(observer);
}
}
}
}
5.在Vie层实现Ivew接口,完成网络请求、数据传递 ,见TestRxJandRetrAct2.java
/**
* Author : Zmj
* Blog : https://blog.csdn.net/Zmj_Dns
* DitHub : https://github.com/ZmjDns
* Time : 2019/1/22
* Description :
*/
public class TestRxJandRetrAct2 extends AppCompatActivity implements IView {
private final String TAG = this.getClass().getSimpleName();
private Observer<LoginResult> observer;
private LoginPersenter loginPersenter; //持有Presenter的引用
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_test_rxjava_retrofit_1);
loginPersenter = new LoginPersenter();
loginPersenter.onAttach(this); //绑定View传到Presenter
}
@Override
public void showLoading() {
}
@Override
public void showData(LoginResult result) {
Log.d(TAG, "showData: INACTIVITY" + result.getDataBean().getToken());
Toast.makeText(this,result.getDataBean().getToken(),Toast.LENGTH_SHORT).show();
}
//调用此方法,用于网络请求
public void mvpLogin(View view){
loginPersenter.login("aaa","123456");
}
@Override
protected void onDestroy() {
loginPersenter.detach();
super.onDestroy();
}
}
至此完成,整个功能。希望能帮助到大家,有错的地方欢迎拍砖。
至于后台,写的特别简单,见Action.java,在Jsp中引入此类,调用getActions(request)方法即可。
public class Actions {
private final String TAG = this.getClass().getSimpleName();
public static final String getActions(HttpServletRequest request) {
try {
request.setCharacterEncoding("utf-8");
} catch (Exception e) {
e.printStackTrace();
}
String responseText = "";
String action = request.getParameter("action");
if (action.equalsIgnoreCase("login")) {
System.out.println("开始返回数据");
responseText = "{\"success\":0,\"msg\":\"aa\",\"dataBean\":{\"token\":\"eyJ1c2VybmFtZSI6ICJ4dXNodW4iLCAiZXhwIjogIjIwMTctMDctMjMgMDY6NTc6MTIifQ==\"}}";
}
return responseText;
}
}