IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android中MVP架构分析(与MVC对比) -> 正文阅读

[移动开发]Android中MVP架构分析(与MVC对比)

参考文章:浅谈 MVP in Android_Hongyang-CSDN博客_android mvp
本文出自:【张鸿洋的博客】

首先,MVP包括三层

M层指model:专门用于处理数据逻辑,类似于MVC中的M,像service,dao层之类的这些。

V层指View:处理视图层的一些控件的展示和隐藏等,负责View的绘制及与用户的交互,对应的实现就是Activity.类似于MVC中的V,html,jsp之类的

P层指Presenter:连接M层和V层,类似于MVC中的C,controller

贴代码详细介绍一下:

先看看布局文件吧

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="15dp">

    <EditText
        android:id="@+id/username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="用户名"
        android:textSize="18sp"
        android:textColor="#000"/>
    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="密码"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="15dp">
        <Button
            android:id="@+id/login"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="登陆"
            android:textSize="20sp" android:layout_marginRight="5dp"/>
        <Button
            android:id="@+id/clear"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="清除"
            android:textSize="20sp"
            android:layout_marginLeft="5dp"/>
    </LinearLayout>
    <ProgressBar
        android:id="@+id/progressbar"
        android:visibility="invisible"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

bean包下的实体类

package com.example.mvptest1.bean;

/**
 * com.example.mvptest1.bean
 *
 * @author yueqingh
 * @date 2021/9/29
 */
public class User {
    private int uid;
    private String name;
    private String password;

    public User() {
    }

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

    public User(int uid, String name, String password) {
        this.uid = uid;
        this.name = name;
        this.password = password;
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    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{" +
                "uid=" + uid +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

model下的接口:因为model层是处理数据逻辑的,所以,定义了

public void login(String name,String password,OnLoginListener loginListener);这个方法,根据这个方法去判断登陆是否成功,所以又定义了一个内部接口OnLoginListener,内部接口中定义了两个方法,分别代表登陆成功和登陆失败
package com.example.mvptest1.model;

import com.example.mvptest1.bean.User;

/**
 * com.example.mvptest1.model
 *
 * @author yueqingh
 * @date 2021/9/29
 */
public interface UserLoginModel {
    interface OnLoginListener{
        void loginSuccess(User user);

        void loginFailed();
    }
    public void login(String name,String password,OnLoginListener loginListener);
}

来看看model的实现吧,这里是没有对loginSuccess(User user)和loginFailed()进行实现的,因为登陆成功有一些view方面的东西需要实现,但是model又必须要和view分开,所以这里没有实现,将这两个方法交给了presenter去实现,因为presenter是连接model和view的。

package com.example.mvptest1.model.Impl;

import com.example.mvptest1.bean.User;
import com.example.mvptest1.model.UserLoginModel;

/**
 * com.example.mvptest1.model.Impl
 *
 * @author yueqingh
 * @date 2021/9/29
 */
public class UserLoginModelImpl implements UserLoginModel {

    @Override
    public void login(final String name, final String password, final OnLoginListener loginListener) {
        //模拟子线程耗时操作
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //模拟登陆成功
                if ("zhangsan".equals(name) && "admin".equals(password)){
                    User user = new User();
                    user.setName(name);
                    user.setPassword(password);
                    loginListener.loginSuccess(user);
                }else {
                    loginListener.loginFailed();
                }
            }
        }).start();
    }
}

model层看完了,我们看看view层,首先看看view层的接口,可以看到这个接口全都是与最前面的布局相关的,也就是view,没有涉及到数据逻辑。

package com.example.mvptest1.view;

import com.example.mvptest1.bean.User;

/**
 * com.example.mvptest1.view
 *
 * @author yueqingh
 * @date 2021/9/29
 */
public interface UserLoginView {
    //获取输入的用户名
    String getUsername();
    //获取输入的密码
    String getPassword();
    //显示进度条
    void showProgress();
    //隐藏进度条
    void hideProgress();
    //清除用户名的输入
    void clearUsername();
    //清楚密码的输入
    void clearPassword();
    //登陆成功的显示,用于项目的时候这里就可以用于Activity的跳转
    void toMainActivity(User user);
    //登陆失败的提示信息显示
    void showFailedError();
}

View的实现是在对应的Activity中实现的,但是我们要先把view和model的关系先建立起来,所以看一下代码

package com.example.mvptest1.presenter;

/**
 * com.example.mvptest1.presenter
 *
 * @author yueqingh
 * @date 2021/9/29
 */
public interface UserLoginPresenter {
    //登陆
    void login();
    //清除
    void clear();
}

presenter的实现

package com.example.mvptest1.presenter.Impl;

import android.os.Handler;

import com.example.mvptest1.bean.User;
import com.example.mvptest1.model.UserLoginModel;
import com.example.mvptest1.presenter.UserLoginPresenter;
import com.example.mvptest1.view.UserLoginView;


/**
 * com.example.mvptest1.presenter.Impl
 *
 * @author yueqingh
 * @date 2021/9/29
 */
public class UserLoginPresenterImpl implements UserLoginPresenter {

    //view
    private UserLoginView userLoginView;
    //model
    private UserLoginModel userLoginModel;
    private Handler handler = new Handler();
    //构造函数
    public UserLoginPresenterImpl(UserLoginView userLoginView, UserLoginModel userLoginModel) {
        this.userLoginView = userLoginView;
        this.userLoginModel = userLoginModel;
    }

    /**
     * 在点击登陆按钮时会调用这个方法,然后到model中处理数据逻辑,在view中进行对应的显示和隐藏
     */
    @Override
    public void login() {
        userLoginModel.login(userLoginView.getUsername(), userLoginView.getPassword(), new UserLoginModel.OnLoginListener() {
            @Override
            public void loginSuccess(final User user) {
                //需要在UI线程执行
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        userLoginView.toMainActivity(user);
                        userLoginView.hideProgress();
                    }
                });
            }

            @Override
            public void loginFailed() {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        userLoginView.showFailedError();
                        userLoginView.showProgress();
                    }
                });
            }
        });
    }

    /**
     * 点击清除按钮时,直接调用view的方法
     */
    @Override
    public void clear() {
        userLoginView.clearUsername();
        userLoginView.clearPassword();
    }
}

最后一步了,model的数据逻辑处理已经处理完毕,view的接口也建立完毕,再然后,model和view的关联也已经建立完毕,接下下我们就处理一些view的实现,在Activity中去调用presenter。

package com.example.mvptest1;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.example.mvptest1.bean.User;
import com.example.mvptest1.model.Impl.UserLoginModelImpl;
import com.example.mvptest1.presenter.Impl.UserLoginPresenterImpl;
import com.example.mvptest1.presenter.UserLoginPresenter;
import com.example.mvptest1.view.UserLoginView;

public class MainActivity extends AppCompatActivity implements UserLoginView, View.OnClickListener {

    private EditText usernameEt;
    private EditText passwordEt;
    private Button loginBtn;
    private Button clearBtn;
    private ProgressBar progressBar;
    //presenter
    private UserLoginPresenter userLoginPresenter;


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

        initViews();
    }

    private void initViews() {
        usernameEt = findViewById(R.id.username);
        passwordEt = findViewById(R.id.password);
        loginBtn = findViewById(R.id.login);
        clearBtn = findViewById(R.id.clear);
        progressBar = findViewById(R.id.progressbar);

        loginBtn.setOnClickListener(this);
        clearBtn.setOnClickListener(this);

        userLoginPresenter = new UserLoginPresenterImpl(this, new UserLoginModelImpl());
    }

    @Override
    public String getUsername() {
        return usernameEt.getText().toString();
    }

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

    @Override
    public void showProgress() {
        progressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideProgress() {
        progressBar.setVisibility(View.GONE);
    }

    @Override
    public void clearUsername() {
        usernameEt.setText("");
    }

    @Override
    public void clearPassword() {
        passwordEt.setText("");
    }

    @Override
    public void toMainActivity(User user) {
        Toast.makeText(MainActivity.this,"loginSuccess",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showFailedError() {
        Toast.makeText(MainActivity.this,"loginFailed",Toast.LENGTH_SHORT).show();
    }

    //根据id判断点击的是哪一个按钮
    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.login:
                userLoginPresenter.login();
                break;
            case R.id.clear:
                userLoginPresenter.clear();
                break;
                default:
                    break;
        }
    }
}

好了,就介绍到这里,写这个东西主要是为了后面回顾,这是我看了张鸿洋大佬的博客和其他很多人的博客最后的总结吧,代码几乎与张鸿洋的一致,没有特别大的改动,因为这个例子确实很生动,易懂,如有理解不到位的地方还请指正,如有侵权的地方,还请联系,立删

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-30 12:02:39  更:2021-09-30 12:05:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:50:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码