android-architecture-components的简单使用分析

公良征
2023-12-01

    近期读了一下Google的architecture-components框架的示例代码,记下自己目前所能理解的东西吧。

    Google示例代码的github地址

    https://github.com/googlesamples/android-architecture-components

先简单介绍一下该框架的主要内容(看了部分源码,还不是很清晰,后面尽量补源码分析,下面只记录一些简单用法):

一、LifecycleObserver

    用于观察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遵循观察者的生命周期,如果不在活跃状态,不会向观察者发送数据改变的信息。

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

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等组件中也适用,使用方法差不多。

 类似资料: