美文网首页
Android Jetpack之ViewModel与LiveDa

Android Jetpack之ViewModel与LiveDa

作者: itfitness | 来源:发表于2021-09-18 10:34 被阅读0次

目录

ViewModel与LiveData的介绍

●ViewModel

ViewModel故名思议是连接View(视图)与Model(数据)之间的桥梁,Jetpack中的ViewModel可以我们降低以前Activity中视图和数据之间的耦合,我们使用ViewModel需要继承androidx.lifecycle.ViewModel如下,其中的onCleared是当与之相关的Activity被销毁是会回调的方法,我们可以在这里进行数据的释放等操作

public class MyViewModel extends ViewModel {
    @Override
    protected void onCleared() {
        super.onCleared();
    }
}
●LiveData

LiveData可以翻译为活着的数据,我们可以通过它来包装数据,进而可以对数据的改变进行监听,结合ViewModel可以很大程度的降低View(视图)与Model(数据)之间的耦合度。

ViewModel与LiveData的使用

1.创建ViewMdel
public class MyViewModel extends ViewModel {

    @Override
    protected void onCleared() {
        super.onCleared();
    }
}
2.ViewMdel中添加LiveData

这里我们使用的是系统提供的MutableLiveData

public class MyViewModel extends ViewModel {
    private MutableLiveData<String> mName;

    public MutableLiveData<String> getName() {
        if(mName == null){
            mName = new MutableLiveData<>();
        }
        return mName;
    }

    @Override
    protected void onCleared() {
        super.onCleared();
    }
}
3.Avticity中绑定ViewMdel并监听LiveData

我们通过ViewModelProvider获取并绑定ViewModel,然后通过获取到的ViewModel获取LiveData,然后通过observe方法对LiveData进行监听,这里我们还添加了一个按钮和一个TextView,当按钮点击的时候我们修改LiveData的值,然后在LiveData的监听方法中将改变后的值赋给TextView,代码如下

public class MainActivity extends AppCompatActivity {
    private TextView tv;
    private Button bt;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        bt = (Button) findViewById(R.id.bt);
        //绑定ViewModel
        MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
        //获取LiveData
        MutableLiveData<String> name = myViewModel.getName();
        //对LiveData进行监听
        name.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                tv.setText(s);
            }
        });
        bt.setOnClickListener(v->{
            name.setValue("数据改变");
        });
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
    <Button
        android:id="@+id/bt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

ViewModel与LiveData的部分源码解析

●ViewModel

根据ViewModel的创建过程我们知道,ViewModel的创建需要ViewModelProvider,我们查看ViewModelProvider的源码发现它的构造函数需要传入ViewModelStoreOwner

 /**
     * Creates {@code ViewModelProvider}. This will create {@code ViewModels}
     * and retain them in a store of the given {@code ViewModelStoreOwner}.
     * <p>
     * This method will use the
     * {@link HasDefaultViewModelProviderFactory#getDefaultViewModelProviderFactory() default factory}
     * if the owner implements {@link HasDefaultViewModelProviderFactory}. Otherwise, a
     * {@link NewInstanceFactory} will be used.
     */
    public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
        this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                : NewInstanceFactory.getInstance());
    }

而我们在MainActivity中调用ViewModelProvider的构造函数时传入的是this,是因为MainActivity继承自了AppCompatActivity而AppCompatActivity又间接继承了ComponentActivity,而ComponentActivity实现了ViewModelStoreOwner接口,因此我们可以将MainActivity的引用作为参数进行传递



接下来我们再看看我们通过查看ViewModelStoreOwner的源码发现,ViewModelStoreOwner接口只有一个getViewModelStore()它返回了ViewModelStore

public interface ViewModelStoreOwner {
    /**
     * Returns owned {@link ViewModelStore}
     *
     * @return a {@code ViewModelStore}
     */
    @NonNull
    ViewModelStore getViewModelStore();
}

我们再查看ViewModelStore的源码发现,它内部对于ViewModel的存储是通过Map实现的

public class ViewModelStore {

    private final HashMap<String, ViewModel> mMap = new HashMap<>();

    final void put(String key, ViewModel viewModel) {
        ViewModel oldViewModel = mMap.put(key, viewModel);
        if (oldViewModel != null) {
            oldViewModel.onCleared();
        }
    }

    final ViewModel get(String key) {
        return mMap.get(key);
    }

    Set<String> keys() {
        return new HashSet<>(mMap.keySet());
    }

    /**
     *  Clears internal storage and notifies ViewModels that they are no longer used.
     */
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }
}

所以我们通过ViewModelProvider创建ViewModel的时候是先查找Map中是否有实例,如果有就取出没有则创建并存储

●LiveData

我们通过查看LiveData的observe方法发现,它是需要LifecycleOwner作为参数传入的

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)

而由于MainActivity的间接父类ComponentActivity已经实现了该接口,因此我们可以将当前Activity的引用作为参数传入,另外我们之前的一篇文章(Android Jetpack之LifeCycle的使用
)已经讲解了通过LifecycleOwner可以实现对Activity生命周期的监听,因此我们可以得知LiveData也是可以监听Activity的生命周期的,我们在LiveData的observe方法源码中也可以看出这一点,它先判断了当前是否在主线程中执行,然后又判断了当前所在的Activity(也可以是Fragment等)是否已经销毁了,如果销毁了就不执行下面的逻辑了,因此使用LiveData也会让我们少处理一些逻辑,因为它内部已经进行判断了

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }

案例源码

https://gitee.com/itfitness/view-model-demo

相关文章

网友评论

      本文标题:Android Jetpack之ViewModel与LiveDa

      本文链接:https://www.haomeiwen.com/subject/bdpegltx.html