Android 架构模式之 MVC

目录

大家好!

作为 Android 程序猿,MVC 应该是我们第一个接触的架构吧,从开始接触 Android 那一刻起,我们就开始接触它,可还记得我们写的第一个 App 代码的样子?

架构设计的目的

通过设计使程序模块化,模块内 高内聚、模块间 低耦合,提高开发效率,便于复用及后续维护。

对 MVC 的理解

上图是 MVC 的架构图,我们都知道,MVC架构中 M 代表 Model(模型)、V 代表 View(视图)、C 代表 Controller(控制器)。它们的职责分别是:

  1. View 负责接收用户的输入事件,然后将事件传递给 Controller;
  2. Controller 收到事件后,会进行业务处理,通知 Model 请求数据;
  3. Model 拿到数据后返回给 Controller 进行后续处理,或者通知 View 更新 UI。

Android 中 MVC 的问题

不幸的是,在 Android 中,通常由 Activity 充当 Controller,与此同时,由于 xml 的弱功能性,导致 Activity 还需要负责视图的显示,所以原本是负责初始化页面的 Activity,就变成了 View 和 Controller 的载体,导致这两部分内容耦合在 Activity 中。后果就是Activity 越来越臃肿、难以维护。这就违反了架构设计的初衷,所以就有了后来的MVP。

试吃个小李子

点击按钮,请求 wanandroid 网站的 banner 接口数据,请求成功后更新到UI上显示接口数据

View

一个Button,点击请求接口数据

一个TextView,用于回显接口返回的数据

activity_main.xml

java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn_get_banner_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="getBannerInfo"
        android:text="@string/get_banner_info" />

    <TextView
        android:id="@+id/tv_banner_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

Model

请求接口

Repository.java

java 复制代码
public final class Repository {

    private ApiService mService;

    private Repository() {
        createService();
    }

    public static Repository getInstance() {
        return SingletonHolder.sInstance;
    }

    private static final class SingletonHolder {
        private static final Repository sInstance = new Repository();
    }

	/**
     * 请求 banner 数据
     */
    public void getBanners(ResponseCallback<List<Banner>> callback) {
        mService.getBanners().enqueue(new Callback<BaseResponse<List<Banner>>>() {
            @Override
            public void onResponse(Call<BaseResponse<List<Banner>>> call, Response<BaseResponse<List<Banner>>> response) {
                BaseResponse<List<Banner>> body = response.body();
                if (response.isSuccessful() && body != null) {
                    if (body.getErrorCode() == 0) {
                        callback.onSuccess(body.getData());
                    } else {
                        callback.onFail(body.getErrorMsg());
                    }
                } else {
                    callback.onFail(response.message());
                }
            }

            @Override
            public void onFailure(Call<BaseResponse<List<Banner>>> call, Throwable throwable) {
                callback.onFail(throwable.getMessage());
            }
        });
    }

    private void createService() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(HttpConstant.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        mService = retrofit.create(ApiService.class);
    }
}

Controller

获取数据

更新UI

MainActivity.java

java 复制代码
public class MainActivity extends AppCompatActivity implements ResponseCallback<List<Banner>> {

    private TextView mBannerInfoTv;

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

        mBannerInfoTv = (TextView) findViewById(R.id.tv_banner_info);
    }

    /**
     * 按钮点击事件
     * @param view
     */
    public void getBannerInfo(View view) {
        getBanners();
    }

    /**
     * 获取 banner 数据
     */
    private void getBanners() {
        Repository.getInstance().getBanners(this);
    }

    @Override
    public void onSuccess(List<Banner> banners) {
        if (banners != null && banners.size() > 0) {
            showBannerInfo(banners);
        }
    }

    @Override
    public void onFail(String msg) {
        Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT);
    }

    /**
     * 更新UI
     * @param banners
     */
    private void showBannerInfo(List<Banner> banners) {
        StringBuilder sb = new StringBuilder("wanandroid 官网\nhttps://www.wanandroid.com\n\n");
        for(Banner item : banners) {
            sb.append(item.getTitle()).append('\n');
        }

        mBannerInfoTv.setText(sb.toString());
    }
}

附上源码链接

致谢:
感谢 wanandroid 提供的开放API

参考:
MVC、MVP、MVVM,我到底该怎么选?

写在最后:

很荣幸成为一名 Android 程序猿,虽然不是一名合格的猿。一路走来磕磕绊绊,借此感谢帮助过我的人,感谢指点、感恩遇见!

相关推荐
稚辉君.MCA_P8_Java1 分钟前
RocketMQ 是什么?它的架构是怎么样的?和 Kafka 又有什么区别?
后端·架构·kafka·kubernetes·rocketmq
蛮三刀酱10 分钟前
复杂度的代价远比你想象得大
java·架构
介一安全43 分钟前
【Frida Android】基础篇15(完):Frida-Trace 基础应用——JNI 函数 Hook
android·网络安全·ida·逆向·frida
吞掉星星的鲸鱼1 小时前
android studio创建使用开发打包教程
android·ide·android studio
陈老师还在写代码1 小时前
android studio 签名打包教程
android·ide·android studio
csj501 小时前
android studio设置
android
hifhf1 小时前
Android Studio gradle下载失败报错
android·ide·android studio
陈老师还在写代码1 小时前
android studio,java 语言。新建了项目,在哪儿设置 app 的名字和 logo。
android·java·android studio
pccai-vip2 小时前
架构论文《论负载均衡的设计与应用》
运维·架构·负载均衡
nbsaas-boot2 小时前
什么语言最适合开发 SaaS 系统:从架构视角的全面分析
java·架构