美文网首页
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