Android Architecture Components学习总结(-)App架构设计指导

1.前言

投入互联网行业已经多年,但是发现自己总结的各类技术文档太少,不觉感慨万千,为了更好的提升自己的技术能力,记录下自己学习的点点滴滴,方便后续参考。该系列文章主要是学习一下谷歌推出的Android Architecture Components,整个学习都是参考谷歌官方文档以及自己的一些实践中的一些个人理解,刚开始写,如有不正确的地方请各路大神吐槽指正。
Android Architecture Components(简称AAC)是谷歌于Google IO 2017发布的辅助开发者设计开发健壮的、可测试和可维护的APP的解决方案,其主要包括两面的内容:
1.管理App的UI组件生命周期(Lifecycle-aware components)
2.数据持久化处理方案(Room)

2.开发者面临的问题

不同于传统的桌面系统在大多数情况下只能从启动快捷方式启动并且作为一个单一的进程运行,Android应用具有更复杂的结构。一个典型的Android应用由多个应用组件构成,涵盖多个Activity、Fragment、Service、Content Provider以及Broadcast Receiver等。大部分的应用组件都是在应用程序清单中声明的,Android系统更具应用程序清单决定应用在用户设备上的整体用户体验。正如前面提到的,传统桌面应用往往作为一个单一的进程运行,但是一个良好设计的Android应用需要更灵活,因为用户在他们设备上安装了不同的应用并且频繁的切换。
以使用社交网络APP分享图片的场景为例,首先App会发出一个请求打开摄像头的Intent,此时用户能够无缝的跳转到相机应用,当然,你也可以在相机应用中进行其它操作,如打开文件选择器并跳转到其它应用,最终回到社交网络App将图片分享出去。在整个分享图片的过程中,任何一个时间点都可能被诸如来电等事件打断,并且在接完电话后回到应用继续进行分享图片。在Android系统中,类似这种App切换行为是非常常见的,所以应用程序需要正确处理这些流程,众所周知,移动设备资源往往是有限的,因此在任何时候操作系统都有可能kill一些应用以腾出空间给新的应用。
所有这一切的关键是你的应用组件能够被单独且有序的调起,同时能够被系统或者用户在任何时候destroyed。由于应用程序组件是短暂的,同时他们的生命周期不在你的控制范围内,所以你不应该在应用组件中存储你应用的数据或者状态且组件之间不应该彼此依赖。

3.通用App架构设计原则

a.分离关注点原则(SOC原则)
分离关注点原则核心就是低耦合,不要将所有的业务逻辑全部写在Activity或者Fragment中,任何不处理UI或者与操作系统交互的逻辑都不应该在Activity或者Fragment中,这样可以避免很多因为组件生命周期相关的问题。这部分代码只是应用和操作系统之间交互的中间层,因为操作系统可能在用户交互或者其它因素(内存低时)杀调它们,尽可能小的依赖它们已提供可靠的用户体验,咱们常用的MVP开发模式就是这个原则的很好体现。
b.模型驱动UI
在设计APP架构时,能够遵循模型驱动UI的原则,最好是持久化模型。持久化数据主要原因有两方面:当系统kill掉你的应用时不会丢失用户数据,此外即使用户网络不稳定或者网络无法连接时,应用依然可以工作。在这里模型是负责处理应用数据的的组件,它独立于应用程序中的View和应用程序组件,因此他们和组件的生命周期问题隔离开来。这样就保持了UI层代码简单且基本无应用逻辑存在,方便管理。

4.谷歌推荐的App架构

基于上述App架构设计原则,如何构建一个APP呢?说句题外话,不可能一个App架构在任何场景下都是最好,但是遵循按照推荐的架构开始一个App设计大多数情况下将是一个好的开始。这里以设计一个UI展示用户配置的示例来说明,用户配置通过REST API获得。
4.1构建用户界面
首先UI由一个fragment及其相应的布局文件组成,为了驱动UI,构造一个包含UserId和User两个数据。接下来创建一个继承自ViewModel的UserProfileViewModel,ViewModel在这里不做详细说明,只要知道它是为UI组件提供数据同时与数据处理模块进行通信,如调用其它组件加载数据或者转发用户对数据的更新,ViewModel独立于View所以它不会受View层的事件影响,如旋转手机屏幕导致Activity重建并不会影响ViewModel。具体代码如下:

public class UserProfileFragment extends Fragment {
    private static final String KEY_UID = "uid";
    private UserProfileViewModel mUserProfileViewModel;

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        String userId = getArguments().getString(KEY_UID);
        mUserProfileViewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class);
        mUserProfileViewModel.init(userId);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.user_profile, container, false);
    }
}
public class UserProfileViewModel extends ViewModel {
    private String mUserId
    private User mUser;

    public void init(String userId) {
        mUserId = userId;
    }

    public User getUser() {
        return mUser;
    }
}

现在我们建立好三个代码模块,我们怎么让他们连接起来啦?当VIewModel的User被设置了值,需要一种方式通知到UI,Google提供了LiveData,它是一个持有具体数据且可被观察,此外它还能感知组件(Activity/Fragement/Service)的生命周期以避免内存泄露。在这里我们用LiveData替换UserProfileViewModel类中的User成员,同时修UserProfileFragment代码,改使得数据变化时能够通知到UI。代码如下:

public class UserProfileViewModel extends ViewModel {
    private String mUserId
    private LiveData<User> mUser;

    public void init(String userId) {
        mUserId = userId;
    }

    public LiveData<User> getUser() {
        return mUser;
    }
}
@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        String userId = getArguments().getString(KEY_UID);
        mUserProfileViewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class);
        mUserProfileViewModel.init(userId);
        mUserProfileViewModel.getUser().observe(this, new Observer<User>() {
            @Override
            public void onChanged(@Nullable User user) {
                //UI更新
            }
        });
    }

和我们常用的回调不一样的是,我们不需要重写Fragment的onStop方法去取消监听变化,如前面所述,LiveData可以自动感知组件的生命周期,当Fragment不存活时不会再回掉onChange,它将在Fragment调用onDestory后自动移除监听器。与此同时,当用户配置(旋转屏幕等)改变时我们也不需要做任何事情,当新的Fragment进入生命周期后,ViewModel可以自动的恢复之前的ViewModel实例及其保存的数据,从这里可以看出VIewModel的生命周期长于View,这就是为什么ViewModel不能直接持有View,否则有可能导致内存泄露。
4.2持久化数据
为了解决需要持久化数据的需求,Google推出了SQLite的ORM解决方案–Room。在这里暂时不做深入讲解,后续还将深入的学习。
4.3整体的APP架构
这里写图片描述
这个框架的最大优点是完全隔离了UI和数据,及Model驱动UI,很好的遵循了上述的APP框架设计准则,后续还将继续深入学习各个库。
附录:
具体如何在自己的项目中引入AAC,请参考官方文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值