近期读了一下Google的architecture-components框架的示例代码,记下自己目前所能理解的东西吧。
Google示例代码的github地址
https://github.com/googlesamples/android-architecture-components
先简单介绍一下该框架的主要内容(看了部分源码,还不是很清晰,后面尽量补源码分析,下面只记录一些简单用法):
用于观察Activity、Fragment等的生命周期,记录当前的活跃状态,可以在LifecycleObserver对Activity生命周期进行监听,处理相关事件,也可以获取当前的状态。下面是简单的使用方式
public class BaseObserver implements LifecycleObserver {
private static final String TAG = BaseObserver.class.getSimpleName();
public BaseObserver(Lifecycle lifecycle)
{
lifecycle.addObserver(this);
Log.i(TAG,"BaseObserver");
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void resume()
{
Log.i(TAG,"resume");
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void stop()
{
Log.i(TAG,"stop");
}
}
Lifecycle为一个抽象类,负责绑定Observer,Activity继承于AppCompatActivity后,其最终继承的SupportActivity实现了LifecycleOwner接口,并且该类里会有Lifecycle的实现,可以直接调用getLifecycle()方法获取Lifecycle对象。
调用Lifecycle的addObserver()方法即可将Observer和Activity绑定在一起。
可以用注解标记对应的生命周期,在对应生命周期执行时,就会调用Observer的对应方法,避免在Activity的生命周期中书写大量代码,导致不易维护。
public class ObserverActivity extends AppCompatActivity{
BaseObserver observer ;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
observer = new BaseObserver(getLifecycle());
}
}
Activity中可以简单地创建Observer,绑定之后即可生效
LiveData是进行数据存储的,可以被观察,与普通的被观察者不同,LiveData遵循观察者的生命周期,如果不在活跃状态,不会向观察者发送数据改变的信息。
LiveData的简单使用
public class LiveDataActivity extends AppCompatActivity {
private static final String TAG = LiveDataActivity.class.getSimpleName();
private MutableLiveData<String> liveData;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
liveData = new MutableLiveData<>();
liveData.setValue(null);
liveData.observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
Log.i(TAG,"s = " + s);
}
});
liveData.setValue("String");
new Handler().postDelayed(() -> liveData.setValue("new String"),1000);
}
}
MutableLiveData继承鱼LiveData,其实现了setValue()和postValue()方法(只是将方法改为了public的)。
上述代码执行后,会在onChange中先打印出“String”,在一秒后,再次调用onChange方法,打印“new String”。
setValue和postValue均为向LiveData更新数据
按照源码中的解释,setValue必须在主线程中使用,在子线程中需要使用postValue进行数据的更新。
/**
* Sets the value. If there are active observers, the value will be dispatched to them.
* <p>
* This method must be called from the main thread. If you need set a value from a background
* thread, you can use {@link #postValue(Object)}
*
* @param value The new value
*/
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
ViewModel的目的是在页面销毁等情况,仍然能够将数据存储下来,再下次创建该页面的时候,直接获取到销毁之前的数据而不是重新加载,可以大幅提升apk的性能,比onSaveInstanceState更加好用,存储的数据范围更广。
由于ViewModel的目的是在页面销毁等场景处理,故不要再ViewModel中持有某个Acvtivity的Context对象,否则会造成内存泄漏。
ViewModel的简单使用:
public class BaseViewModel extends AndroidViewModel {
private MutableLiveData<List<User>> users;
private Handler mHandler = new Handler();
private int index;
public BaseViewModel(Application application) {
super(application);
}
public LiveData<List<User>> getUsers()
{
if(null == users)
{
users = new MutableLiveData<>();
users.setValue(null);
loadUsers();
}
return users;
}
private void loadUsers() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
List<User> userList = new ArrayList<>();
userList.add(new User("Bob",index++));
users.postValue(userList);
mHandler.postDelayed(this,2000);
}
},2000);
}
}
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView contentTextView = findViewById(R.id.txt);
viewModel = ViewModelProviders.of(this).get(BaseViewModel.class);
viewModel.getUsers().observe(this, users -> {
Log.i("mtfTest","users = " + users);
contentTextView.setText(null == users ? "users is null" : users.toString());
});
}
}
ViewModel一般结合LiveData使用,LiveData的数据存放在ViewModel中。
ViewModel的创建使用ViewMpdelProviders这个类,其原理是如果没有该ViewModel类的对象,就创建新的对象,如果已有ViewModel对象,就取出旧的ViewModel对象,这样Activity在销毁重建后,还是能取出之前的数据,节省掉了重复加载数据的场景。
ViewModel创建的简单流程:
/**
* Returns an existing ViewModel or creates a new one in the scope (usually, a fragment or
* an activity), associated with this {@code ViewModelProvider}.
* <p>
* The created ViewModel is associated with the given scope and will be retained
* as long as the scope is alive (e.g. if it is an activity, until it is
* finished or process is killed).
*
* @param modelClass The class of the ViewModel to create an instance of it if it is not
* present.
* @param <T> The type parameter for the ViewModel.
* @return A ViewModel that is an instance of the given type {@code T}.
*/
public <T extends ViewModel> T get(Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
/**
* Returns an existing ViewModel or creates a new one in the scope (usually, a fragment or
* an activity), associated with this {@code ViewModelProvider}.
* <p>
* The created ViewModel is associated with the given scope and will be retained
* as long as the scope is alive (e.g. if it is an activity, until it is
* finished or process is killed).
*
* @param key The key to use to identify the ViewModel.
* @param modelClass The class of the ViewModel to create an instance of it if it is not
* present.
* @param <T> The type parameter for the ViewModel.
* @return A ViewModel that is an instance of the given type {@code T}.
*/
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
viewModel = mFactory.create(modelClass);
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
在源码中可以看到,创建之后会存在mViewModelStore中(实际里面是一个HashMap),如果已经创建过的ViewModel,直接从Map中取出即可。
对于相同的类,可以设定不同的key创建多个对象。
LifecycleObserver的作用是监听Activity的生命周期,可以根据生命周期做对应的处理,比如LiveData的内部实现就是通过LifecycleObserver做的监听,判断是否活跃,在活跃状态才会通知Observer进行更新。
LiveData的主要作用是数据存储,通过Observer的回调,通知数据改变,并且只在观察者活跃状态才会通知。
ViewModel的强大在于,可以将数据与Activity独立区分,使数据不收Activity的生命周期影响,在Activity销毁重建等场景,不再重复请求加载数据。
同样,该框架不局限于Activity,在Fragment等组件中也适用,使用方法差不多。