美文网首页
Android MVP简单例子

Android MVP简单例子

作者: 皮皮铭 | 来源:发表于2019-09-25 15:43 被阅读0次

    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

    相关文章

      网友评论

          本文标题:Android MVP简单例子

          本文链接:https://www.haomeiwen.com/subject/fsodyctx.html