Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LiveData初次登场 #28

Open
soapgu opened this issue Apr 9, 2021 · 0 comments
Open

LiveData初次登场 #28

soapgu opened this issue Apr 9, 2021 · 0 comments
Labels
mvvm This issue or pull request already exists 安卓 安卓

Comments

@soapgu
Copy link
Owner

soapgu commented Apr 9, 2021

  • 前言

    其实在学习过程中一直有接触到,但是始终是似懂非懂。对这个组件也没有一个初步的定位和理解。
    我第一次想用LiveData的时候是在学习Binding特性的时候。但是对于数据的变化可以由Observable 代劳,LiveData并不是唯一的选择。这样就会产生一个疑惑,那么LiveData是为Binding而生的吗,那么既然没有LiveData也可以做Binding。那么LiveData的真正价值在哪里。我回答不了这个问题。只能暂时搁置,暂缓使用。

  • LiveData出道

我在实际使用过程中出现这样的场景。我想要在某个ViewModel中执行跳转到其他Activity的Intent操作,但是这个操作是不被Android设计者鼓励

  1. Intent的生成需要在Activity内执行,startActivity这个API本身就是Activity的成员函数
  2. ViewModel禁止拥有Activity的引用,MVVM界的共识,本身解耦分家的两个部件又搅合在一起,本身就是违法架构原则。其二,Activity的生命周期要比ViewModel要短,增加引用还会引起不必要的内存泄露

迫于无奈我只能写出这样别扭的诡异的代码

protected void onCreate(Bundle savedInstanceState) {
        Logger.i( "---Create MainActivity----" );
        super.onCreate(savedInstanceState);
        HomeViewModel viewModel = new ViewModelProvider(this,
                ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication()))
                .get(HomeViewModel.class);
        ActivityMainBinding binding  = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.setDatacontext( viewModel );
        binding.searchButton.setOnClickListener( v -> {
            Intent intent = new Intent(this, SearchActivity.class);
            startActivity(intent);
        } );
    }

感觉就是革命不彻底的表现

LiveData终于横空出世

  • 特性1 变化

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者

这是数据变化,和个特性和Observable有重合

  • 特性2 根据观察者生命周期推送,释放退订变化

如果观察者(由 Observer 类表示)的生命周期处于 STARTED 或 RESUMED 状态,则 LiveData 会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察 LiveData 对象而注册的非活跃观察者不会收到更改通知。
您可以注册与实现 LifecycleOwner 接口的对象配对的观察者。有了这种关系,当相应的 Lifecycle 对象的状态变为 DESTROYED 时,便可移除此观察者。这对于 Activity 和 Fragment 特别有用,因为它们可以放心地观察 LiveData 对象,而不必担心泄露(当 Activity 和 Fragment 的生命周期被销毁时,系统会立即退订它们)。

这个特性才是关键,这里已经很明确说了,就是为Activity 和 Fragment量身定做的,目的就是建立起UI Control层(Activity,Fragment)和ViewModel的联系

  • LiveData家族(相关Package)

dependencies {
    def lifecycle_version = "2.2.0"

    // ViewModel and LiveData
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
    // alternatively - just ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" // use -ktx for Kotlin
    // alternatively - just LiveData
    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
    // alternatively - Lifecycles only (no ViewModel or LiveData). Some UI
    //     AndroidX libraries use this lightweight import for Lifecycle
    implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"

    annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" // use kapt for Kotlin
    // alternately - if using Java8, use the following instead of lifecycle-compiler
    implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"

    // optional - ReactiveStreams support for LiveData
    implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version" // use -ktx for Kotlin

    // optional - Test helpers for LiveData
    testImplementation "androidx.arch.core:core-testing:$lifecycle_version"
}
  • LiveData使用示例

在build.gradle中添加
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

在MainViewModel.java中加入LiveData字段

private MutableLiveData<Class<?>> targetActivity;

public MutableLiveData<Class<?>> getTargetActivity() {
        if( targetActivity == null )
            targetActivity = new MutableLiveData<>();
        return targetActivity;
    }

泛型类代表传入显示Activity的类型

public void GoToRecognizeActivity()
    {
        this.targetActivity.setValue(RecognizeActivity.class);
    }

按钮触发的逻辑就是设置LiveData的值,把要跳转的Activity类型通知出去

MainActivity.java中订阅LiveData

 viewModel.getTargetActivity().observe(this, t->{
            Intent intent = new Intent(this,t);
            startActivity(intent);
        });

这样清晰的多了,Activity里面还是做startActivity的事情,ViewModel管好业务和数据逻辑,大家各司其职。

  • LiveData的副产品 绑定通知

  class ViewModelActivity extends AppCompatActivity {
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           // Inflate view and obtain an instance of the binding class.
           UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);

           // Specify the current activity as the lifecycle owner.
           binding.setLifecycleOwner(this);
       }
   }

注意如果把 LiveData用做绑定需要加上 binding.setLifecycleOwner(this);

@soapgu soapgu added the 安卓 安卓 label Apr 9, 2021
@soapgu soapgu added the mvvm This issue or pull request already exists label Jun 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mvvm This issue or pull request already exists 安卓 安卓
Projects
None yet
Development

No branches or pull requests

1 participant