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 程序猿,虽然不是一名合格的猿。一路走来磕磕绊绊,借此感谢帮助过我的人,感谢指点、感恩遇见!

相关推荐
Dingdangr4 小时前
Android中的Intent的作用
android
技术无疆4 小时前
快速开发与维护:探索 AndroidAnnotations
android·java·android studio·android-studio·androidx·代码注入
GEEKVIP4 小时前
Android 恢复挑战和解决方案:如何从 Android 设备恢复删除的文件
android·笔记·安全·macos·智能手机·电脑·笔记本电脑
Karoku0667 小时前
【网站架构部署与优化】web服务与http协议
linux·运维·服务器·数据库·http·架构
Lill_bin9 小时前
深入理解ElasticSearch集群:架构、高可用性与数据一致性
大数据·分布式·elasticsearch·搜索引擎·zookeeper·架构·全文检索
zyhJhon9 小时前
软考架构-面向服务的架构风格
架构
nbsaas-boot10 小时前
微服务之间的安全通信
安全·微服务·架构
Jouzzy11 小时前
【Android安全】Ubuntu 16.04安装GDB和GEF
android·ubuntu·gdb
极客先躯12 小时前
java和kotlin 可以同时运行吗
android·java·开发语言·kotlin·同时运行
数据运营新视界13 小时前
你知道企业架构中核心的4大架构联系和不同吗?
大数据·架构