【大前端】【Android】把 Activity 重构成 MVVM 的对比示例

同一个功能:加载用户并显示名字

功能不变:

点按钮 → 请求用户 → 显示用户名 → 失败提示


一、❌ 传统 Activity 写法(所有东西都在 Activity)

Activity(UI类)

复制代码
public class UserActivity extends AppCompatActivity {

    TextView tvName;
    Button btnLoad;

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

        tvName = findViewById(R.id.tvName);
        btnLoad = findViewById(R.id.btnLoad);

        btnLoad.setOnClickListener(v -> {
            // ① UI 事件
            loadUser();
        });
    }

    private void loadUser() {
        // ② 业务逻辑
        showLoading();

        Api.getUser(new Callback<User>() {
            @Override
            public void onSuccess(User user) {
                // ③ 数据处理
                tvName.setText(user.getName());   // 改 UI
                hideLoading();
            }

            @Override
            public void onError(String msg) {
                // ④ 错误处理
                Toast.makeText(UserActivity.this, msg, Toast.LENGTH_SHORT).show();
                hideLoading();
            }
        });
    }
}

❗问题在哪?

问题 原因
Activity 很胖 所有职责都在
不可测试 依赖 Android
UI & 逻辑耦合 直接操作 View
状态不可控 loading / error 到处写

二、✅ 重构目标(先不看代码)

我们要做到:

复制代码
Activity:我只管展示
ViewModel:我管逻辑和状态

Activity 不再知道

  • 请求怎么发

  • 什么时候成功 / 失败

  • 状态怎么切换


三、✅ MVVM 写法(拆开)


1️⃣ ViewModel:专门"管状态"

复制代码
public class UserViewModel extends ViewModel {

    // 用户名状态
    private MutableLiveData<String> userName = new MutableLiveData<>();

    // loading 状态
    private MutableLiveData<Boolean> loading = new MutableLiveData<>();

    // 错误信息
    private MutableLiveData<String> errorMsg = new MutableLiveData<>();

    public LiveData<String> getUserName() {
        return userName;
    }

    public LiveData<Boolean> getLoading() {
        return loading;
    }

    public LiveData<String> getErrorMsg() {
        return errorMsg;
    }

    public void loadUser() {
        loading.setValue(true);

        Api.getUser(new Callback<User>() {
            @Override
            public void onSuccess(User user) {
                userName.setValue(user.getName()); // 只改数据
                loading.setValue(false);
            }

            @Override
            public void onError(String msg) {
                errorMsg.setValue(msg);             // 只抛状态
                loading.setValue(false);
            }
        });
    }
}

📌 注意一个关键点

ViewModel 从头到尾没有一句 UI 代码


2️⃣ Activity:变成"数据监听器"

复制代码
public class UserActivity extends AppCompatActivity {

    private UserViewModel viewModel;
    private TextView tvName;
    private ProgressBar progressBar;
    private Button btnLoad;

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

        tvName = findViewById(R.id.tvName);
        progressBar = findViewById(R.id.progressBar);
        btnLoad = findViewById(R.id.btnLoad);

        viewModel = new ViewModelProvider(this).get(UserViewModel.class);

        // ① 监听数据
        viewModel.getUserName().observe(this, name -> {
            tvName.setText(name);
        });

        viewModel.getLoading().observe(this, show -> {
            progressBar.setVisibility(show ? View.VISIBLE : View.GONE);
        });

        viewModel.getErrorMsg().observe(this, msg -> {
            if (msg != null) {
                Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
            }
        });

        // ② 把点击事件"交出去"
        btnLoad.setOnClickListener(v -> {
            viewModel.loadUser();
        });
    }
}

四、最重要的一行对比(🔥核心)

以前

复制代码
tvName.setText(user.getName());

现在

复制代码
userName.setValue(user.getName());

👉 UI 更新从"命令式"变成"数据驱动"


五、用一句话理解"重构发生了什么"

Activity 不再"做事"
ViewModel 不再"碰 UI"
它们通过"状态"交流


六、责任变化对照表(一定要看)

职责 以前 现在
点击处理 Activity Activity(转交)
网络请求 Activity ViewModel
成功失败判断 Activity ViewModel
UI 更新 Activity Activity
状态来源 Activity ViewModel

七、已经"半只脚进 MVVM 了"的标志

如果现在能理解这句话:

Activity 不知道"什么时候该改 UI",
它只知道"数据变了我就展示"

那已经抓住 MVVM 的核心原理 了。

相关推荐
Doro再努力7 小时前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
Daniel李华7 小时前
echarts使用案例
android·javascript·echarts
做人不要太理性8 小时前
CANN Runtime 运行时组件深度解析:任务调度机制、存储管理策略与维测体系构建逻辑
android·运维·魔珐星云
我命由我123458 小时前
Android 广播 - 静态注册与动态注册对广播接收器实例创建的影响
android·java·开发语言·java-ee·android studio·android-studio·android runtime
木斯佳9 小时前
前端八股文面经大全:26届秋招滴滴校招前端一面面经-事件循环题解析
前端·状态模式
朗迹 - 张伟9 小时前
Tauri2 导出 Android 详细教程
android
hepingfly9 小时前
不再单打独斗!用 Agent Teams 让 7 个 Claude 同时帮你开发
状态模式
lpruoyu9 小时前
【Android第一行代码学习笔记】Android架构_四大组件_权限_持久化_通知_异步_服务
android·笔记·学习
独自破碎E10 小时前
【BISHI15】小红的夹吃棋
android·java·开发语言
C澒13 小时前
Remesh 框架详解:基于 CQRS 的前端领域驱动设计方案
前端·架构·前端框架·状态模式