android开发笔记之MVP

MVP

下面这个图,就解释了MVP的数据流:
android开发笔记之MVP_第1张图片
其中MVP,核心为Presenter,View与Model没有数据之间的交互。而MVC,核心为Controller,View与Model有数据之间的交互。

所以MVP最大的优点就是Model与View之间的完全解耦。

MVP的权威资料

android 架构
https://github.com/googlesamples/android-architecture
todo-mvp 架构 github网站
https://github.com/googlesamples/android-architecture/tree/todo-mvp/

当你下载google官方的Demo后,建议你好好看看。

android开发笔记之MVP_第2张图片

如果你一脸懵逼,可能你需要一些说明的资料:
Android官方MVP架构项目解析
http://www.android-doc.com/androiddocs/2017/0803/1218.html

这样参照对比的看,你才会看出来一点门道的。

MVP Demo 登录操作

这是我参考官方Demo,再结合Android中用到的MVP模式
https://blog.csdn.net/weixin_28774815/article/details/80960779
一个文件,一行代码的慢慢debug,才完成的Demo。

先看效果图:
android开发笔记之MVP_第3张图片
也就是输入用户名:test,密码:1234,点击CLICK,完成登录操作,如果登录成功,弹出登录成功提示,或者弹出登录失败提示。

代码的整件目录如下:
android开发笔记之MVP_第4张图片

先与界面布局文件:




    

    

    

然后,再直接从官网将BasePresenter.java和BaseView.java复制过来。

public interface BasePresenter {

    void start();

}
public interface BaseView {

    void setPresenter(T presenter);

}

再定义一个IModel接口:

public interface  IModel {

}

然后实现LoginMode类,主要是实现一个登录的操作:

public class LoginMode implements IModel {

    private String mUserName = "test";
    private String mPassWord = "1234";

    private LoginLisentener loginLisentener;

    public void login(String username, String password) {
        if (loginLisentener == null) {
            return;
        }

        if (mUserName.equals(username) && mPassWord.equals(password)){
            loginLisentener.onSeccess();
        } else {
            loginLisentener.onFails();
        }
    }

    public void setLoginLisentener(LoginLisentener loginLisentener) {
        this.loginLisentener = loginLisentener;
    }

    public interface LoginLisentener {
        void onSeccess();
        void onFails();
    }
}

下面再实现一个LoginContract类,这就是官方说的契约类。
在这个类中, 我们定义了View 接口,主要有二个接口,分别来表示登录时成功和失败的界面相关的操作。
再定义了Presenter 接口,主要是为了执行登录操作的总入口。

public class LoginContract {

    public interface View extends BaseView {

        void onLoginSeccess();

        void onLoginFails();

    }

    public interface Presenter extends BasePresenter {

        void onLogin(String name, String password);

    }

}

下面就是我们的核心类LoginPresenter,一般来说view和model都是其成员方法,一个构造方法,还有就是其定义的核心登录操作接口onLogin,而start一般就是实现一些初始化操作:

public class LoginPresenter implements LoginContract.Presenter{

    private static final String TAG = "LoginPresenter";

    private final LoginContract.View mView;
    private  LoginMode loginMode;

    public LoginPresenter(final LoginContract.View mView) {
        this.mView = mView;
        this.loginMode = new LoginMode();
        loginMode.setLoginLisentener(new LoginMode.LoginLisentener() {
            @Override
            public void onSeccess() {
                mView.onLoginSeccess();
            }

            @Override
            public void onFails() {
                mView.onLoginFails();
            }
        });
    }

    @Override
    public void onLogin(String name, String password) {
        loginMode.login(name, password);
    }

    @Override
    public void start() {
        Log.i(TAG,"start");
    }
}

而最后,在MVPDemoMainActivity界面登录时,我们就是只要调用:loginPresenter.onLogin(getUserName(),getPassword());
就可以完成登录的逻辑了。

public class MVPDemoMainActivity extends AppCompatActivity implements LoginContract.View{

    private static final String TAG = "MVPDemoMainActivity";

    private EditText user_name;
    private EditText password;
    private Button button;

    private LoginContract.Presenter loginPresenter;

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

    private void init() {
        user_name = (EditText) findViewById(R.id.user_name);
        password = (EditText) findViewById(R.id.password);
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                loginPresenter.onLogin(getUserName(),getPassword());
            }
        });

        loginPresenter = new LoginPresenter(this);
        loginPresenter.start();

    }

    private String getUserName(){
        return user_name.getText().toString();
    }

    private String getPassword(){
        return password.getText().toString();
    }

    @Override
    public void onLoginSeccess() {
        Toast.makeText(getApplicationContext(), "登陆成功!", Toast.LENGTH_LONG).show();
        Log.i(TAG,"onLoginSeccess");
    }

    @Override
    public void onLoginFails() {
        Toast.makeText(getApplicationContext(), "登陆失败!", Toast.LENGTH_LONG).show();
        Log.i(TAG,"onLoginFails");
    }

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

    @Override
    protected void onDestroy() {
        super.onDestroy();
        this.loginPresenter = null;
    }

}

MVP+OKhttp Demo 获取网络信息

从最简单的Android MVP讲起
https://www.jianshu.com/p/4736ebe1114b
我们参考上面这个例子,来实现一个mvp+okhttp的例子

输入一个网络地址,获取网络信息,再显示出来。
android开发笔记之MVP_第5张图片

成功获取网络信息:
android开发笔记之MVP_第6张图片

获取网络信息失败:
android开发笔记之MVP_第7张图片

具体代码结构:
android开发笔记之MVP_第8张图片

添加库依赖 app\build.gradle

dependencies {
    implementation("com.squareup.okhttp3:okhttp:3.14.1")
    implementation("com.squareup.okio:okio:2.2.2")
}

在AndroidManifest.xml文件中添加网络权限


MainView.java代码:

public interface MainView {

    void getMessage(String message);
    void error();

}

MainModel.java代码

public class MainModel {

    public Call getData(String url) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        return client.newCall(request);
    }
}

MainPresenter.java代码:

public class MainPresenter {

    private MainView mainView;
    private MainModel model;

    public MainPresenter(MainView mainView) {
        this.mainView = mainView;
        model=new MainModel();
    }

    public void getUrlData(String url){
        model.getData(url).enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                mainView.error();
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                mainView.getMessage(response.body().string());
            }
        });
    }
}

MVPDemo02MainActivity .java

public class MVPDemo02MainActivity extends AppCompatActivity implements MainView{

    private TextView resultTextView;
    private MyHandler handler;

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

    private void init() {
        Button button = (Button)findViewById(R.id.button);
        handler = new MyHandler(this);
        final EditText editText = (EditText)findViewById(R.id.et_url);
        resultTextView = (TextView)findViewById(R.id.tv_result);
        final MainPresenter presenter = new MainPresenter(this);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String url = editText.getText().toString();
                presenter.getUrlData(url);
            }
        });
    }

    @Override
    public void getMessage(String message) {
        Message msg = handler.obtainMessage(0, message);
        handler.sendMessage(msg);
    }

    @Override
    public void error() {
        Message msg = handler.obtainMessage(1, "error");
        handler.sendMessage(msg);
    }

    private static class MyHandler extends Handler {
        private WeakReference reference;

        private MyHandler(MVPDemo02MainActivity activity) {
            reference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MVPDemo02MainActivity activity = reference.get();
            switch (msg.what) {
                case 0:
                    activity.resultTextView.setText(msg.obj.toString());
                    break;
                case 1:
                    activity.resultTextView.setText(msg.obj.toString());
                    break;
            }
        }
    }
}

你可能感兴趣的:(android开发笔记)