Android MVC 写法

前言

Model:负责数据逻辑

View:负责视图逻辑

Controller:负责业务逻辑

持有关系:

1、View 持有 Controller

2、Controller 持有 Model

3、Model 持有 View

辅助工具:ViewBinding

执行流程:View ==> Controller ==> Model ==> View

案例效果图:

1、定义Controller接口

java 复制代码
/**
 * 控制器接口 负责业务逻辑
 */
public interface IController extends IBaseController {

    void setModel(IModel model); // 持有model

    /**
     * 这些都是方法,都是由 View 调用的
     */

    void onDataChanged(String data); // 监听输入文本事件,通知 Model

    void submitFrom(); // 提交表单事件,通知 Model

    void clearData(); // 清空按钮点击事件,通知 Model

}

1.1、实现Controller接口

java 复制代码
/**
 * 业务逻辑 具体实现
 */
public class IControllerImp implements IController {

    private IModel model;

    @Override
    public void setModel(IModel model) {
        this.model = model;
    }

    @Override
    public void removeHandlerMsgAndCallback() {
        model.removeHandlerMsgAndCallback();
    }

    @Override
    public void onDataChanged(String data) {
        model.onDataChanged(data);
    }

    @Override
    public void submitFrom() {
        model.submitFromData();
    }

    @Override
    public void clearData() {
        model.clearData();
    }
}

2、定义Model接口

java 复制代码
/**
 * 数据模型接口 负责数据逻辑
 */
public interface IModel extends IBaseModel {

    void setView(IView view); // 持有View

    /**
     * 这些都是方法,都是由 Controller 调用的
     */

    void onDataChanged(String data); // 监听文本变化,时时更新数据后,通知 View

    void submitFromData(); // 提交表单数据后,通知 View

    void clearData(); // 清空数据后,通知 View

}

2.1、实现Model接口

java 复制代码
/**
 * 数据模型逻辑 具体实现
 */
public class IModelImp implements IModel {

    private String mData = "";
    private Handler handler = new Handler();
    private IView iview;

    @Override
    public void setView(IView view) {
        this.iview = view;
    }

    @Override
    public void removeHandlerMsgAndCallback() {
        handler.removeCallbacksAndMessages(null);
    }

    @Override
    public void onDataChanged(String data) {
        mData = data;
        iview.onDataChangedUpdateText(data);
    }

    @Override
    public void submitFromData() {
        iview.showSubmitFromLoading(mData);
        handler.removeCallbacksAndMessages(null);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                iview.hideSubmitFromLoading();
            }
        }, 1500);
    }

    @Override
    public void clearData() {
        mData = "";
        iview.clearFromData();
    }
}

3、定义View接口

java 复制代码
/**
 * 视图接口 负责视图逻辑
 */
public interface IView extends IBaseView {

    default void setController(IController controller) {} // 持有控制器,根据View事件,通知 Controller

    /**
     * 这些都是方法,都是由 Model 调用的
     */

    void onDataChangedUpdateText(String data); // 根据时时数据更新TextView

    void showSubmitFromLoading(String data); // 显示loading

    void hideSubmitFromLoading(); // 隐藏loading

    void clearFromData(); // 清空EditText数据

}

3.1、实现View接口

java 复制代码
/**
 * 视图逻辑 具体实现
 */
public class MVCActivity extends AppCompatActivity implements IView,View.OnClickListener {

    private IModel iModel; // 数据层 M
    private IController iController; // 控制器层 C
    private AlertDialog dialog;

    private ActivityMvcBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMvcBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        iModel = new IModelImp();
        iController = new IControllerImp();

        // 注意一下,写的顺序

        iModel.setView(this); // 持有View
        iController.setModel(iModel); // 持有Model
        setController(iController); // 持有控制器

        init();
    }

    @Override
    public void onClick(View v) {
        if (v == binding.submitBtn) {
            iController.submitFrom();
        } else if (v == binding.clearBtn) {
            iController.clearData();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        iController.removeHandlerMsgAndCallback();
    }

    private void init() {
        binding.editMsg.setText("normal");
        binding.edit.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                iController.onDataChanged(s.toString());
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
        binding.submitBtn.setOnClickListener(this);
        binding.clearBtn.setOnClickListener(this);
    }

    @Override
    public void onDataChangedUpdateText(String data) {
        binding.editMsg.setText(data);
    }

    @Override
    public void showSubmitFromLoading(String data) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        TextView textView = new TextView(this);
        if (TextUtils.isEmpty(data)) {
            data = "normal";
        }
        textView.setText("正在提交:" + data);
        builder.setCancelable(false);
        builder.setView(textView);
        dialog = builder.show();
    }

    @Override
    public void hideSubmitFromLoading() {
        dialog.dismiss();
    }

    @Override
    public void clearFromData() {
        binding.edit.setText("");
        binding.editMsg.setText("normal");
    }
}

4、IBaseController

java 复制代码
/**
 * Base 控制器接口 负责业务逻辑
 */
public interface IBaseController {

    // 写一些,公用或者通用的方法,用于扩展

    default void removeHandlerMsgAndCallback() {} // 删除handler 回调和消息

}

5、IBaseModel

java 复制代码
/**
 * Base 数据模型接口 负责数据逻辑
 */
public interface IBaseModel {

    // 写一些,公用或者通用的方法,用于扩展

    default void removeHandlerMsgAndCallback() {} // 删除handler 回调和消息

}

6、IBaseView

java 复制代码
/**
 * Base 视图接口 负责视图逻辑
 */
public interface IBaseView {

    // 写一些,公用或者通用的方法,用于扩展

    default void testBaseView() {}

}

7、activity_mvc.xml

java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".ui.activity.MVCActivity">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="@color/material_dynamic_primary90"
        app:title="MVC" />

    <EditText
        android:id="@+id/edit"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginHorizontal="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/toolbar" />

    <TextView
        android:id="@+id/edit_msg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        app:layout_constraintLeft_toLeftOf="@id/edit"
        app:layout_constraintTop_toBottomOf="@id/edit" />

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/submit_btn"
        android:layout_width="match_parent"
        android:layout_height="58dp"
        android:layout_marginHorizontal="16dp"
        android:layout_marginTop="8dp"
        android:text="submit"
        android:textAllCaps="false"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/edit_msg" />

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/clear_btn"
        android:layout_width="match_parent"
        android:layout_height="58dp"
        android:layout_marginHorizontal="16dp"
        android:layout_marginTop="8dp"
        android:text="clear"
        android:textAllCaps="false"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/submit_btn" />

</androidx.constraintlayout.widget.ConstraintLayout>

8、源码地址

GitHub - LanSeLianMa/AndroidMVC: Android MVC 写法

9、其他写法

Android MVP 写法-CSDN博客

Android MVVM 写法-CSDN博客

相关推荐
杨筱毅17 小时前
【底层机制】Android低内存管理机制深度解析
android·底层机制
二流小码农17 小时前
鸿蒙开发:this的指向问题
android·ios·harmonyos
循环不息优化不止18 小时前
Jetpack Compose 状态管理
android
友人.22719 小时前
Android 底部导航栏 (BottomNavigationView) 制作教程
android
努力学习的小廉20 小时前
初识MYSQL —— 事务
android·mysql·adb
阿里云云原生20 小时前
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
android
.豆鲨包20 小时前
【Android】Android内存缓存LruCache与DiskLruCache的使用及实现原理
android·java·缓存
JulyYu21 小时前
【Android】针对非SDK接口的限制解决方案
android·客户端
猪哥帅过吴彦祖1 天前
Flutter 系列教程:应用导航 - Navigator 1.0 与命名路由
android·flutter·ios
2501_916008891 天前
iOS 跨平台开发实战指南,从框架选择到开心上架(Appuploader)跨系统免 Mac 发布全流程解析
android·macos·ios·小程序·uni-app·iphone·webview