MVP
M:数据请求
V:视图
P:M和V交互的桥梁
MVP模式的好处:
1.View与Model完全隔离。
2.利于维护。
3.利于写单元测试
弊:
代码多。
简单的登录例子
image.png
首先回调接口:
public interface CallBack {
//成功返回
void onSuccess();
//失败返回
void onFilure(String msg);
}
M层:
接口
public interface IUserModel {
void login(String user, String pwd, CallBack callBack);
}
实现IUserModel接口,延迟发送来模范访问网络
public class UserModel implements IUserModel {
private Handler handler=new Handler(Looper.getMainLooper());
@Override
public void login(final String user, final String pwd, final CallBack callBack) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (user.equals("123456") && pwd.equals("123456")){
callBack.onSuccess();
}else {
callBack.onFilure("账号或密码错误");
}
}
},2000 );
}
}
V层
接口LoginView继承BaseMvpView接口,LoginView接口可以根据自己的需要去定义。
public interface BaseMvpView {
//显示等待框
void showLoding(String msg);
//隐藏等待框
void hideLoding();
//错误信息
void showerr(String err);
}
public interface LoginView extends BaseMvpView{
//成功返回信息
void showResult(String msg);
//Toast信息
void showToast(String msg);
}
P层
public class BaseMvpPresenter<V extends BaseMvpView> implements Presenter<V> {
private V mvpView;
@Override
public void attachView(V mvpView) {
this.mvpView = mvpView;
}
@Override
public void deachView() {
mvpView = null;
}
/**
* 判断 view是否为空
* @return
*/
public boolean isAttachView(){
return mvpView != null;
}
/**
* 返回目标view
* @return
*/
public V getMvpView(){
return mvpView;
}
/**
* 检查view和presenter是否连接
*/
public void checkViewAttach(){
if(! isAttachView()){
throw new MvpViewNotAttachedException();
}
}
/**
* 自定义异常
*/
public static class MvpViewNotAttachedException extends RuntimeException {
public MvpViewNotAttachedException() {
super("请求数据前请先调用 attachView(MvpView) 方法与View建立连接");
}
}
}
BaseMvpPresenter类主要是处理P层的一些错误,例如view销毁了,但是p层还在调用v层的方法,就会导致空指针。
ILoginPresenter 定义一个接口
public interface ILoginPresenter {
void login(String user,String pwd);
}
LoginPresenter 类实现ILoginPresenter 接口,在login里面接受MainActivity传过来的值,做校验处理,通过 userModel.login传数据过去M层做网络处理,然后通过CallBack回调,调用 loginView.showResult("登录成功");把结果返回给Activity.
public class LoginPresenter extends BaseMvpPresenter<LoginView> implements ILoginPresenter {
private UserModel userModel;
public LoginPresenter(UserModel userModel) {
this.userModel = userModel;
}
@Override
public void login(String user, String pwd) {
checkViewAttach();//检查是否绑定
//获取View实例
final LoginView loginView = getMvpView();
if (user.length() == 0 && pwd.length() == 0) {
loginView.showToast("账号密码不能为空");
} else {
loginView.showLoding("正在登录");
userModel.login(user, pwd, new CallBack() {
@Override
public void onSuccess() {
loginView.hideLoding();
loginView.showResult("登录成功");
}
@Override
public void onFilure(String msg) {
loginView.hideLoding();
loginView.showerr(msg);
}
});
}
}
}
Activity实现LoginView接口
public class MainActivity extends AppCompatActivity implements LoginView {
private LoginPresenter loginPresenter;
private ProgressDialog progressDialog;
private EditText et1, et2;
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
loginPresenter = initPresenter();
loginPresenter.attachView(this);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
loginPresenter.login(et1.getText().toString().trim(), et2.getText().toString().trim());
}
});
}
public LoginPresenter initPresenter() {
return new LoginPresenter(new UserModel());
}
private void initView() {
et1 = findViewById(R.id.et1);
et2 = findViewById(R.id.et2);
btn = findViewById(R.id.btn);
progressDialog = new ProgressDialog(this);
}
@Override
public void showResult(String msg) {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void showToast(String msg) {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void showLoding(String msg) {
progressDialog.setMessage(msg);
if (!progressDialog.isShowing())
progressDialog.show();
}
@Override
public void hideLoding() {
if (progressDialog.isShowing())
progressDialog.dismiss();
}
@Override
public void showerr(String err) {
Toast.makeText(getApplicationContext(), err, Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
loginPresenter.deachView();
}
}
123.gif
MVP RecyclerView 简单实例
image.png
回调 CallBack2,跟上面不同,加了泛型,因为要返回实体类。
public interface CallBack2<T> {
//成功返回
void onSuccess(T t);
//失败返回
void onFilure(String msg);
}
M层
接口没什么好说的,就一个获取数据的接口,回调参数
public interface IMain2Model {
void getData( CallBack2<mybean> callBack);
}
模仿网络操作
public class Main2Model implements IMain2Model {
private Handler handler = new Handler(Looper.getMainLooper());
@Override
public void getData(final CallBack2<mybean> callBack) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
String string = "{\n" +
" \"students\": [\n" +
" {\n" +
" \"name\": \"jadyli\",\n" +
" \"gender\": \"male\",\n" +
" \"age\": 18\n" +
" },\n" +
" {\n" +
" \"name\": \"Juliet\",\n" +
" \"gender\": \"female\",\n" +
" \"age\": 20\n" +
" }\n" +
" ]\n" +
"}";
final mybean mybean = new Gson().fromJson(string, mybean.class);
for (int i=0;i<mybean.getStudents().size();i++){
callBack.onSuccess(mybean);
}
}
}, 1000);
}
}
V层
接口
public interface Main2View<T> extends BaseMvpView {
//成功返回信息
void showResult(T t);
//Toast信息
void showToast(String msg);
}
P层
接口
public interface IMain2Presenter {
void getData();
}
基本跟登录的一样
public class Main2Presenter extends BaseMvpPresenter<Main2View> implements IMain2Presenter {
private Main2Model main2Model;
public Main2Presenter(Main2Model main2Model) {
this.main2Model = main2Model;
}
public void getData() {
checkViewAttach();//检查是否绑定
final Main2View main2View = getMvpView();
main2View.showLoding("正在加载数据");
main2Model.getData(new CallBack2<mybean>() {
@Override
public void onSuccess(mybean mybean) {
main2View.showResult(mybean);
}
@Override
public void onFilure(String msg) {
}
});
}
}
Main2Activity代码
public class Main2Activity extends AppCompatActivity implements Main2View {
private static final String TAG = "Main2Activity";
private RecyclerView rv;
private ProgressDialog progressDialog;
private List<mybean> list;
private MyAdapter adapter;
private LinearLayoutManager manager;
private Main2Presenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
list = new ArrayList<>();
initView();
presenter = initPresenter();
presenter.attachView(this);
presenter.getData();
}
private void initView() {
rv = findViewById(R.id.rv);
progressDialog = new ProgressDialog(this);
}
@Override
public void showResult(Object o) {
mybean mybean = (com.gzfyit.mvp3.mybean.mybean) o;
list.add(mybean);
Log.e(TAG, "showResult: " + list);
adapter = new MyAdapter(getApplicationContext(), list);
manager = new LinearLayoutManager(getApplicationContext());
rv.setLayoutManager(manager);
rv.setAdapter(adapter);
}
@Override
public void showToast(String msg) {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void showLoding(String msg) {
progressDialog.setMessage(msg);
if (!progressDialog.isShowing())
progressDialog.show();
}
@Override
public void hideLoding() {
if (progressDialog.isShowing())
progressDialog.dismiss();
}
@Override
public void showerr(String err) {
Toast.makeText(getApplicationContext(), err, Toast.LENGTH_SHORT).show();
}
public Main2Presenter initPresenter() {
return new Main2Presenter(new Main2Model());
}
}
MyAdapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private static final String TAG = "MyAdapter";
private Context context;
private List<mybean> list;
public MyAdapter(Context context, List<mybean> list) {
this.context = context;
this.list = list;
}
@NonNull
@Override
public MyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyAdapter.ViewHolder holder, int position) {
Log.e(TAG, "onBindViewHolder: " + list.size());
mybean mybean = list.get(position);
holder.tv_num.setText(mybean.getStudents().get(position).getName());
}
@Override
public int getItemCount() {
return list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView tv_num;
public ViewHolder(@NonNull View itemView) {
super(itemView);
tv_num = itemView.findViewById(R.id.tv_num);
}
}
}
123.gif
网友评论