android开发笔记之MVP

MVP

下面这个图,就解释了MVP的数据流:
在这里插入图片描述
其中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架构项目解析
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。

先看效果图:
在这里插入图片描述
也就是输入用户名:test,密码:1234,点击CLICK,完成登录操作,如果登录成功,弹出登录成功提示,或者弹出登录失败提示。

代码的整件目录如下:
在这里插入图片描述

先与界面布局文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MVPDemoMainActivity">

    <EditText
        android:id="@+id/user_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="input user name"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <EditText
        android:id="@+id/password"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="input password"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/user_name"/>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click"
        app:layout_constraintTop_toBottomOf="@id/password"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>

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

public interface BasePresenter {

    void start();

}
public interface BaseView<T> {

    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<Presenter> {

        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的例子

输入一个网络地址,获取网络信息,再显示出来。
在这里插入图片描述

成功获取网络信息:
在这里插入图片描述

获取网络信息失败:
在这里插入图片描述

具体代码结构:
在这里插入图片描述

添加库依赖 app\build.gradle

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

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

<uses-permission android:name="android.permission.INTERNET"/>

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<MVPDemo02MainActivity> 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;
            }
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hfreeman2008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值