AAC---ViewModel

时间:2022-06-13
本文章向大家介绍AAC---ViewModel,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

ViewModel介绍

ViewModel是用来保存并且管理与LifeCycle以及UI相关数据的数据结构。ViewModel允许数据在Configuration改变时(比如屏幕旋转)保存,并且在旋转后恢复。

UI Controller相关的Android框架则是Activity与Fragment。而FrameWork可能由于用户的操作,设备系统事件决定销毁或者重建UI Controller,而这些操作则完全不可控。而当UI Controller被重建或者销毁时候,任何transient UI相关的数据都会丢失。

例如你的APP可能包括了很多用户的数据,当Activity因为Configuration改变而重建时,新的Activity需要重新获取这些数据,而一般会使用onSaveInstanceState方法保存,并且使用onCreate中的Bundle进行恢复,但是这种只适合非常小并且实现了序列化以及反序列化的数据,而不能保存大数据,比如Bitmap等。

最后,ViewModel非常有效的帮我们从UI Controller隔离了View与数据之间的逻辑关系。

使用ViewModel

  1. 在build.gradle中添加配置
dependencies {
    def lifecycle_version = "1.1.1"

    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    // alternatively - just ViewModel
    implementation "android.arch.lifecycle:viewmodel:$lifecycle_version" // use -ktx for Kotlin
    // alternatively - just LiveData
    implementation "android.arch.lifecycle:livedata:$lifecycle_version"
    // alternatively - Lifecycles only (no ViewModel or LiveData).
    //     Support library depends on this lightweight import
    implementation "android.arch.lifecycle:runtime:$lifecycle_version"

    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
    // alternately - if using Java8, use the following instead of compiler
    implementation "android.arch.lifecycle:common-java8:$lifecycle_version"

}
  1. 实现ViewModel与LiveData绑定。
  • 在ViewModel中提供数据来源repository,如Room或者网络
  • 在数据返回后,使用LiveData向UI Controller提供UI相关数据
public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<User>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}
  1. 在Activity或者Fragment中生成对应的ViewModel
public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        // Create a ViewModel the first time the system calls an activity's onCreate() method.
        // Re-created activities receive the same MyViewModel instance created by the first activity.
        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}

ViewModel的生命周期

这样即使Activity被重建了,通过ViewModelProviders得到的ViewModel对象还是第一个Activity创建的对象。而当Activity被销毁时,Framework会回调ViewModel对象的onCleared方法,以至于可以让我们在该方法内部进行资源清理,避免内存泄漏。

生命周期

ViewModel绝对不能引用View,LifeCycle或者任何一个引用了Activity的对象,否则可能会导致内存泄漏。如果ViewModel需要引用到Application的话,那么则需要使用AndroidViewModel对象。

在Fragment之间共享数据

通过同一个Activity获取到的ViewModel对象相同,所以可以通过ViewModelProvider获取到的ViewModel对象是同一个。而这么做的好处有:

  • Activity不需要做任何事情,或者不需要知道Fragment之间有什么交流
  • Fragment也不需要知道ViewModel相互之间的关系,一旦另外一个Fragment消失,另外一个也会运行正常。
  • 每个Fragment都有自己的生命周期,这样ViewModel不会被任何一个Fragment的周期干扰。一旦一个Fragment替换了另一个,那么UI也不会出问题
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 Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, item -> {
           // Update the UI.
        });
    }
}

参考资料

ViewModel Lifecycle Aware Data Loading with Architecture Components Jetpack