- 在android的开发中,MVP肯定都早有听闻,但是真正应用在项目中的是少之又少,因为MVP带来的一个缺点是类的爆炸。
- 下面简单分析下MVP的结构
从上图分析可以看出,MVP = Model + View + Presenter. Model是专门负责处理数据的请求和接收以及一些处理,而View就是我们的Activity,是专门负责页面的处理,类似页面跳转,显示listview等等,而Presenter就是业务逻辑的处理了,他是协调View和Model之间的中间层。为什么说用了标准的MVP会带来类的爆炸呢?
首先Model需要创建一个interface和一个实现类,View需要一个interface加上Activity,Presenter一个类,而且这些类还不能复用,因为每个activity的逻辑和接口都不一样,对比以前我们自己写Activity的时候,类是从一个变成了5个。要是一个中等的项目。类乘上5倍,那将是想当的可怕。
MVP最初创建的时候是为了给Activity解耦的,而不是用来添堵的。那我们总得想个法子去减少这些类,首先是Model + Presenter.其实在项目中,如何不是很负责的数据,我们完全可以直接在Presenter完成对数据的请求和简单处理,这样我们就可以少了两个类,其次,我们可以用上Retrofit,Retrofit的接口都是interface.我们大可以复用这个类,如果太多,我们增加一个类即可。这样,整个项目中,不会有太多的interface。
下面是简单的代码:Beans-SchoolClass
package rxjava.application.com.androidmyp.Beans;
/**
* Created by Qiujc on 2016/5/9.
*/
public class SchoolClass extends BaseBean<SchoolClass> {
private int id;
private String className;
private String teacher;
private String grade;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getTeacher() {
return teacher;
}
public void setTeacher(String teacher) {
this.teacher = teacher;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
@Override
public String toString() {
return "SchoolClass{" +
"id=" + id +
", className='" + className + '\'' +
", teacher='" + teacher + '\'' +
", grade='" + grade + '\'' +
'}';
}
}
Data - ApiCenter 网络接口
package rxjava.application.com.androidmyp.Data;
import com.google.gson.JsonObject;
import java.util.HashMap;
import java.util.List;
import retrofit.Call;
import retrofit.http.FieldMap;
import retrofit.http.FormUrlEncoded;
import retrofit.http.POST;
import retrofit.http.Query;
import rx.Observable;
import rxjava.application.com.androidmyp.Beans.BaseBean;
import rxjava.application.com.androidmyp.Beans.SchoolClass;
import rxjava.application.com.androidmyp.Beans.User;
/**
* Created by Qiujc on 2016/4/14.
* 定义网络的接口
*/
public interface ApiCenter {
@POST("/user_login")
Observable<BaseBean<User>> UserLogin(@Query("username")String username, @Query("password") String password);
@POST("/user_login")
Call<JsonObject> UserLoginWithRetrofit(@Query("username")String username,@Query("password") String password);
@FormUrlEncoded
@POST("/instalment1.4/api/test/getClassData")
Observable<BaseBean<List<SchoolClass>>> getClass(@FieldMap HashMap<String,String> hashMap);
}
Data-ApiManager 初始化Retrofit
package rxjava.application.com.androidmyp.Data;
import com.squareup.okhttp.OkHttpClient;
import retrofit.GsonConverterFactory;
import retrofit.Retrofit;
import retrofit.RxJavaCallAdapterFactory;
/**
* Created by Qiujc on 2016/4/14.
*/
public class ApiManger {
private static ApiManger apiManger;
public static ApiManger getIntance() {
synchronized (ApiManger.class) {
if (apiManger == null) {
apiManger = new ApiManger();
}
}
return apiManger;
}
public ApiCenter api;
public ApiManger() {
OkHttpClient okHttp = new OkHttpClient();
Retrofit.Builder builder = new Retrofit.Builder();
builder.baseUrl("http://172.16.1.174");
builder.addConverterFactory(GsonConverterFactory.create());
builder.addCallAdapterFactory(RxJavaCallAdapterFactory.create());
builder.client(okHttp);
Retrofit restAdapter = builder.build();
api = restAdapter.create(ApiCenter.class);
}
}
View-UserLoginContract–activity的接口
package rxjava.application.com.androidmyp.Login;
import rxjava.application.com.androidmyp.Presenter.BaseView;
/**
* Created by Qiujc on 2016/4/13.
*/
public interface UserLoginContract extends BaseView{
void loginSuccess();
void loginFailed();
void showToast(String msg);
}
View-UserLogin —-activity
package rxjava.application.com.androidmyp.Login;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import butterknife.Bind;
import butterknife.ButterKnife;
import rxjava.application.com.androidmyp.BaseActivity;
import rxjava.application.com.androidmyp.Home.HomeActivity;
import rxjava.application.com.androidmyp.Presenter.LoginPresenter;
import rxjava.application.com.androidmyp.R;
public class UserLogin extends BaseActivity implements UserLoginContract {
@Bind(R.id.userName)
EditText userName;
@Bind(R.id.passWord)
EditText passWord;
@Bind(R.id.sureToLogin)
Button sureToLogin;
private LoginPresenter loginPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_login);
ButterKnife.bind(this);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowHomeEnabled(true);
//create presenter
this.presenter = new LoginPresenter(this);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
loginPresenter.getClassInfo();
}
});
sureToLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loginPresenter.loginWithRetrofit(userName.getText().toString(), passWord.getText().toString());
}
});
}
@Override
public void loginSuccess() {
Toast.makeText(this, "user login success!", Toast.LENGTH_SHORT).show();
startActivity(new Intent(UserLogin.this, HomeActivity.class));
this.finish();
}
@Override
public void loginFailed() {
Toast.makeText(this, "user login Failed!", Toast.LENGTH_SHORT).show();
}
@Override
public void showToast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
@Override
public void setPresenter(Object presenter) {
this.presenter = loginPresenter = (LoginPresenter) presenter;
}
}
Presenter-LoginPresenter–负责acvity的业务处理
package rxjava.application.com.androidmyp.Presenter;
import java.util.HashMap;
import java.util.List;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.functions.Func1;
import rx.subscriptions.CompositeSubscription;
import rxjava.application.com.androidmyp.Beans.BaseBean;
import rxjava.application.com.androidmyp.Beans.SchoolClass;
import rxjava.application.com.androidmyp.Data.ApiException;
import rxjava.application.com.androidmyp.Data.ApiInterceptor;
import rxjava.application.com.androidmyp.Data.ApiManger;
import rxjava.application.com.androidmyp.Data.RxSchedulers;
import rxjava.application.com.androidmyp.Login.UserLoginContract;
/**
* Created by Administrator on 2016/4/13.
*/
public class LoginPresenter implements BasePresenter{
private UserLoginContract mView;//当前的页面
private CompositeSubscription msubscription;//管理所有的订阅
public LoginPresenter(UserLoginContract mView) {
this.mView = mView;
this.mView.setPresenter(this);
this.msubscription = new CompositeSubscription();
}
/**
* 获取class
*/
public void getClassInfo() {
HashMap<String, String> map = new HashMap<>();
map.put("id", "3");
Subscription i = ApiManger.getIntance().api.getClass(map)
.flatMap(new Func1<BaseBean<List<SchoolClass>>, Observable<List<SchoolClass>>>() {
@Override
public Observable<List<SchoolClass>> call(BaseBean<List<SchoolClass>> listBaseBean) {
return new ApiInterceptor().flatResult(listBaseBean);
}
})
.compose(RxSchedulers.<List<SchoolClass>>IO_Main())
.subscribe(new Subscriber<List<SchoolClass>>() {
@Override
public void onCompleted() {
//获取数据完成
mView.loginSuccess();
}
@Override
public void onError(Throwable e) {
ApiException apiException = (ApiException) e;
mView.showToast(apiException.getRespMSg());
}
@Override
public void onNext(List<SchoolClass> schoolClasses) {
//得到数据,在页面可以进行数据绑定操作
}
});
this.msubscription.add(i);//把订阅加入管理集合中
}
@Override
public void onDestroy() {
//在activity结束生命周期的时候取消订阅,解除对context的引用
if(msubscription != null){
this.msubscription.unsubscribe();
}
}
}
详细的代码:源码下载
总结:android mvp是一个很好的架构,我们可以利用他很好的解耦Acitivity,我们不能让他成为我们的累赘!