欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

android学习笔记-MVP实例

程序员文章站 2024-03-15 18:24:00
...

        最近在疯狂学习mvp架构,看了一堆博文也没整明白,最后还是谷歌的官方案例给整明白了,遂整理记录,有错误的地方,还请大神们指教。

android学习笔记-MVP实例

        mvp基本结构如图,view持有presenter,presenter持有view和model,presenter通过持有的model存取数据,通过持有的view获取view中的数据,或改变view的ui显示。可以看到view中有个set方法,主要是方便外部注入presenter实例,这里是通过presenter中持有的view来调用setpresenter()将presenter自己的实例注入到view中去,至于原因请看这里。最后实现了view和model的解耦,所有的业务逻辑都放在presenter内操作,和view解耦,view只负责ui的展示。

        这里以简单的login界面距离介绍。为了简介起见,所有的layout和jdbc相关的操作都不作具体展示。首先是java文件,如下:

android学习笔记-MVP实例

android学习笔记-MVP实例

android学习笔记-MVP实例

首先定义三个接口,代表mvp三个模块,然后用一个contract接口来管理,之后是三个实现类,这里fragment对应的是view,而activity只用来做一些初始化操作。最后需要一个user的pojo,便于从数据库存取数据。具体代码如下:

1、User

public class User {

    private Integer id;
    private String name;
    private String password;

    public User(Integer id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }

    public User(){}

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

没啥好说,属性对应的数据库列属性,其他方法都自动生成

2、Base

public interface BaseModel<T> {

    T loadModel(Context context, String name);

    void saveModel(T model);

}

public interface BasePresenter {

    void start() throws ExecutionException, InterruptedException;

}

public interface BaseView<T> {

    void setPresenter(T presenter);

}

最*抽象

3、contract

public interface LoginContract {

    interface View extends BaseView<Presenter> {

        void setProgressIndicator(boolean active);

        String getName();

        String getPassword();

        void setName(String name);

        void setPassword(String psw);

        void showToast(String text);

    }

    interface Presenter extends BasePresenter{

    }

}

扩展了一些方法,用contract管理

4、activity

public class LoginActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        LoginFragment loginFragment = new LoginFragment();
        ActivityUtil.addFragmentToActivity(getSupportFragmentManager(),loginFragment,R.id.loginfrm);

        //初始化整个mvp架构
        new LoginPresenter(loginFragment,new LoginModel(),this);
    }
}

只做初始化,绑定fragmnet

5、view

public class LoginFragment extends Fragment implements LoginContract.View{

    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    private LoginContract.Presenter mPresenter;
    private EditText nameEdit;
    private EditText pswEdit;
    private Button loginButton;

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    public LoginFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment LoginFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static LoginFragment newInstance(String param1, String param2) {
        LoginFragment fragment = new LoginFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View root = inflater.inflate(R.layout.fragment_login, container, false);
        nameEdit = root.findViewById(R.id.name);
        pswEdit = root.findViewById(R.id.psw);
        loginButton = root.findViewById(R.id.bt_login);
        loginButton.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                try {
                    mPresenter.start();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        return root;
    }

    @Override
    public void setProgressIndicator(boolean active) {

    }

    @Override
    public String getName() {
        return nameEdit.getText().toString();
    }

    @Override
    public String getPassword() {
        return pswEdit.getText().toString();
    }

    @Override
    public void setName(String name) {

    }

    @Override
    public void setPassword(String psw) {

    }

    @Override
    public void setPresenter(LoginContract.Presenter presenter) {
        this.mPresenter = presenter;
    }

    public void showToast(String text){
        Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT).show();
    }
}

没用到的方法先不管,两个edittext,一个button,两个get方法方便presenter取数据,一个showToast方法显示状态,按下button启动presenter

6、model

public class LoginModel implements BaseModel {

    private User mUser;

    private SharedPreferences mPrefs;

    private Query mQuery;

    LoginModel(){
        mUser = new User();
        mQuery = QueryFactory.createMysqlQuery();
    }

    @Override
    public User loadModel(Context context, String name) {
        //根据用户名返回user对象
        List list = mQuery.queryRows(context,"select * from user where name=?",User.class,new Object[]{name});
        if(list.size()==0){
            return new User();
        }
        return (User)list .get(0);
    }

    @Override
    public void saveModel(Object model) {
        mQuery.insert(model);
    }
}

同样没用到的属性和方法先不管,关键是一个query对象,主要是管理jdbc操作数据库的,然后根据username查找并返回给presenter

7、presenter

public class LoginPresenter implements LoginContract.Presenter{

    private LoginContract.View mView;

    private LoginModel mModel;

    private Context mContext;

    public LoginPresenter(LoginContract.View loginView,LoginModel loginModel,Context context){
        mView = loginView;
        mModel = loginModel;
        mContext = context;
        loginView.setPresenter(this);
    }

    @Override
    public void start() throws ExecutionException, InterruptedException {
        User remoteUser = new User();
        Thread loadThread = new Thread(new Runnable(){
            @Override
            public void run() {
                User user = mModel.loadModel(mContext,mView.getName());
                remoteUser.setId(user.getId());
                remoteUser.setName(user.getName());
                remoteUser.setPassword(user.getPassword());
            }
        });
        loadThread.start();
        loadThread.join();
        User typeUser = new User();
        typeUser.setName(mView.getName());
        typeUser.setPassword(mView.getPassword());
        int state = checkValid(typeUser,remoteUser);
        switch (state){
            case 0:
                mView.showToast("登录成功!");
                break;
            case 1:
                mView.showToast("用户名不存在!");
                break;
            case 2:
                mView.showToast("密码错误!");
                break;
            case 3:
                mView.showToast("请输入用户名!");
                break;
            case 4:
                mView.showToast("请输入密码!");
                break;
        }
    }

    private int checkValid(User typeUser,User remoteUser){
        String typeName = typeUser.getName();
        String typePSW = typeUser.getPassword();
        String remoteName = remoteUser.getName();
        String remotePsw = remoteUser.getPassword();
        if(typeName.equals("")){
            return 3;
        }
        if(typePSW.equals("")){
            return 4;
        }
        if(remoteName==null){
            return 1;
        }
        if(remotePsw!=null&&!typePSW.equals(remotePsw)){
            return 2;
        }
        return 0;
    }
}

presenter分别从view和model两边接收两个user对象,并作比较,从而显示登录状态提示