新款安卓架构设计-Architecture Components介绍

架构模板篇介绍了mvp,mvi,mvvm(databinding),今天介绍的这款安卓架构框架是Google在今天5月17号推出的:Architecture Components. 它的第一版本解决如下问题:
1)自动管理activity和fragment的生命周期,从而避免资源和内存溢出问题
2)持续化java对象到sqlite数据库

主要包括组成部分:
1)Lifecycle Components
2)LiveData
3)ViewModel
4)Rom (Database, entity, DAO)

它的两个主要设计原则:
1)单一原则,不要把所有代码都写在Activity/Fragment, 隔离独立的模块
2)model(数据)驱动UI

完整的架构图:
这里写图片描述

1.添加到项目工程

allprojects {
    repositories {
        jcenter()
        maven { url 'https://maven.google.com' }
    }
}

Lifecycles,LiveData, ViewModel,添加依赖:

compile "android.arch.lifecycle:runtime:1.0.0-alpha3"
compile "android.arch.lifecycle:extensions:1.0.0-alpha3"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha3"

Room,添加依赖

compile "android.arch.persistence.room:runtime:1.0.0-alpha3"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha3"

添加Room的test依赖:

testCompile "android.arch.persistence.room:testing:1.0.0-alpha3"

添加room的rxjava支持依赖:

compile "android.arch.persistence.room:rxjava2:1.0.0-alpha3"

2.处理Lifecycles

Lifecycle持有Activity/Fragment的lifecycle状态,允许其他对象观察这些状态变化。使用下面两种枚举类跟踪关联组件的lifecycle状态:
1)Event
2)State
其对应的活动图:
这里写图片描述

在代码中,使用@Annotation的方式标识对应的关联组件的生命周期

class MyLocationListener implements LifecycleObserver {
    private boolean enabled = false;
    public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {
       ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void start() {
        if (enabled) {
           // connect
        }
    }

    public void enable() {
        enabled = true;
        if (lifecycle.getState().isAtLeast(STARTED)) {
            // connect if not connected
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void stop() {
        // disconnect if connected
    }
}

3.LiveData

LiveData是一个保存value和观察value变化的对象。不像其他的observable,它可以关联lifecycle.如果Observer的生命周期处于STARTED或RESUMED状态,则LiveData会将Observer视为活动状态。看下对面的代码片段:

public class LocationLiveData extends LiveData<Location> {
    private LocationManager locationManager;

    private SimpleLocationListener listener = new SimpleLocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            setValue(location);
        }
    };

    public LocationLiveData(Context context) {
        locationManager = (LocationManager) context.getSystemService(
                Context.LOCATION_SERVICE);
    }

    @Override
    protected void onActive() {
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
    }

    @Override
    protected void onInactive() {
        locationManager.removeUpdates(listener);
    }
}

LiveData有三个方法:
1)onActive() 当LiveData有一个激活的observer时调用;
2)onInactive() 当LiveData没有任何激活的observer时调用;
3)setValue() 调用该方法更新LiveData的value,并通知相关的observer

在Fragment中使用LiveData:

public class MyFragment extends LifecycleFragment {
    public void onActivityCreated (Bundle savedInstanceState) {
        LiveData<Location> myLocationListener = ...;
        Util.checkUserStatus(result -> {
            if (result) {
                myLocationListener.addObserver(this, location -> {
                    // update UI
                });
            }
        });
    }
}

它具有如下优势:
1)没有内存泄漏:因为它的observers绑定到对应的Lifecycle对象,所以当Lifecycle销毁了,对应的LiveData也会被清除
2)不会导致Crash而停止activities,同样因为Lifecycle影响observer,当observer处于inactive状态,不会去接收event
3)总是更新到最新数据,这个很方便
4)正确处理configuration change(比如屏幕旋转),当屏幕旋转后,他仍然可以获取最新的可用数据
5)共享资源,可以把LiveData弄成单例模式
6)因为它绑定了Lifecycle,所以不需要手动管理Activity/Fragment对应的生命周期了。

4.ViewModel

它的设计就是为了保存和管理UI关联的数据,这样使得configuration change(比如屏幕旋转)发生时,数据可以恢复。

回顾下Activity恢复数据,如果Activity被重新创建或者发生屏幕旋转,保存和恢复周期

onCreate()
onSaveInstanceState()
onRestoreInstanceState()

但是它有缺点:只允许保存少量的数量,对于需要保存大量的数据:比如界面上所有的用户列表信息,无能为力。

Lifecycle提供了ViewModel,它负责为UI提供数据,ViewModel会自动保留当发生屏幕旋转时。这样就实现了代码分离:ViewModel负责准备数据,而不是放在Activity/Fragment中。

下面打代码示例演示了它是怎么使用的:

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<Users>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // do async operation to fetch users
    }
}

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}

它的实现原理:activity被重新创建后,它会使用同样的ViewModel实例(上一个Activity创建的),当对应的activity被销毁了,框架会 调用ViewModel的onCleared方法来销毁资源。

注意:由于ViewModel超出了具体的Activity和Fragment实例生命周期,所以它不应该引用View或任何可能持有对活动上下文的引用的类。 如果ViewModel需要应用程序上下文(例如,找到系统服务),则可以扩展AndroidViewModel类,并在构造函数中接收应用程序的构造函数(因为Application类扩展了Context)

4.1实现fragment之间数据共享

很常见,一个Activity有多个Fragment, 而实现fragment之间的数据共享或者叫数据传递比较麻烦

fragment.setArgs(Bundle)
Bundle bundle = fragment.getArgs()

而ViewModel帮我们简化了,看下下面的代码示例

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}

public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends LifecycleFragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, { item ->
           // update UI
        });
    }
}

这种机制的优势:
1)对activity来说,它是完全隔离,不知道任何fragment之间的细节
2)fragment之间不需要互相关注,除了ViewModel的细节
3)fragment实现互相独立。

5.Room

Room是一个持续library,Room在SQLite上提供了一个抽象层,以便在利用SQLite的全部功能的同时使流畅的数据库访问。它包括了三个主要组件:
1)Database
2)Entity
3)DAO

Room的架构设计图如下:
这里写图片描述

从左到右的顺序:database, DAO, entity

下面几个代码判断,展示了怎么编写这几个组件,以及怎么使用

1)Entity

@Entity
public class User {
    @PrimaryKey
    private int uid;

    @ColumnInfo(name = "first_name")
    private String firstName;

    @ColumnInfo(name = "last_name")
    private String lastName;

    // Getters and setters are ignored for brevity,
    // but they're required for Room to work.
}

2)DAO

@Dao
public interface UserDao {
    @Query("SELECT * FROM user")
    List<User> getAll();

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    List<User> loadAllByIds(int[] userIds);

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND "
           + "last_name LIKE :last LIMIT 1")
    User findByName(String first, String last);

    @Insert
    void insertAll(User... users);

    @Delete
    void delete(User user);
}

3)Database

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}

4)使用

AppDatabase db = Room.databaseBuilder(getApplicationContext(),
        AppDatabase.class, "database-name").build();

5.总结

Lifecycle, LiveData,ViewModel,Room看起来是独立的,确实它们各自负责各自的功能,但是它们一旦串联起来,你会发现很多头疼的问题,比如:代码分离,数据持续化,异步加载结束确保Activity/Fragment没有被销毁后刷新UI,这些问题都透过架构的方式帮我们处理好了,既然它有这么多的优势还是值得一用的。

但是需要注意的是:它怎么样也只是一个架构模板,如果你有比它更好用的架构模板,可以比较之后再做出选择。

官方例子:
https://github.com/googlesamples/android-architecture-components

我的fork:https://github.com/Sherchen/android-architecture-components

来自developer上的blog:
https://android-developers.googleblog.com/2017/05/android-and-architecture.html

来自youtube上的官方video介绍:
https://www.youtube.com/watch?v=vOJCrbr144o

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值