Android Jetpack组件 - ViewModel,LiveData使用以及原理

本文涉及的源码版本如下:

  • com.android.support:appcompat-v7:27.1.1
  • android.arch.lifecycle:extensions:1.1.1
  • android.arch.lifecycle:viewmodel:1.1.1
  • android.arch.lifecycle:livedata:1.1.1

什么是ViewModel, 以及工作原理

ViewModel用于存储和管理UI相关的数据,ViewModel有自己生命周期,会根据fragment,activity的生命周期销毁。当配置发生改变时, ViewModel存储的数据还是存在的,不会被销毁。(例如旋转屏幕,旋转屏幕通常会导致activity重建)

ViewModel 相关类结构

ViewModel:抽象类,onCleared方法用于释放资源

AndroidViewModel: 继承了ViewModel, 没什么区别, 构造可以传入一个application

ViewModelStore: ViewModel存储器, 内部Map存储

ViewModelStoreOwner: 一个接口, ViewModelStore拥有者。 Fragment和FragmentActivity实现了接口

Factory: 一个工厂接口,用于创建ViewModel。是ViewModelProvider的内部接口

NewInstanceFactory: 继承Factory, 通过反射class.newInstance()产生一个ViewModel。所以使用这个Factory,ViewModel需要有空参构造器。

AndroidViewModelFactory: 继承Factory, 也是通过反射产生一个AndroidViewModel, 而且这个AndroidViewModel构造器必须只有一个application参数, 如何反射创建失败会调用NewInstanceFactory去创建。

ViewModelProvider: 是一个帮助类,构造器可以传入ViewModelStore和Factory, 会根据Factory产生一个ViewModel, 并存储到ViewModelStore里。

ViewModel的生命周期

ViewModel的生命周期是跟fragment, activity生命周期关联的。只有fragment, activity销毁时才会调用ViewModel.onCleared() (配置改成导致销毁,不会调用onCleared)

ViewModel存储在ViewModelStore, ViewModel的onCleared方法在ViewModelStore的clear方法时被调用, ViewModelStore源码如下:

private final HashMap<String, ViewModel> mMap = new HashMap<>();
/**
     *  Clears internal storage and notifies ViewModels that they are no longer used.
     */
public final void clear() {
    for (ViewModel vm : mMap.values()) {
        vm.onCleared();
    }
    mMap.clear();
}
复制代码

下面看看Fragment, 和FragmentActivity的实现,先看Fragment的实现:

public ViewModelStore getViewModelStore() {
    if (getContext() == null) {
        throw new IllegalStateException("Can‘t access ViewModels from detached fragment");
    }
    // new一个ViewModelStore, 一个Fragment只有一个ViewModelStore
    if (mViewModelStore == null) {
        mViewModelStore = new ViewModelStore();
    }
    return mViewModelStore;
}

public void onDestroy() {
    mCalled = true;
    // Use mStateSaved instead of isStateSaved() since we‘re past onStop()
    if (mViewModelStore != null && !mHost.mFragmentManager.mStateSaved) {
        mViewModelStore.clear(); // mStateSaved用于判读是否由于配置改变导致Fragment重建
    }
}
复制代码

再看FragmentActivity的实现

    public ViewModelStore getViewModelStore() {
        if (getApplication() == null) {
            throw new IllegalStateException("Your activity is not yet attached to the "
                    + "Application instance. You can‘t request ViewModel before onCreate call.");
        }
        if (mViewModelStore == null) {
            mViewModelStore = new ViewModelStore();
        }
        return mViewModelStore;
    }

    protected void onDestroy() {
        super.onDestroy();
		....
        if (mViewModelStore != null && !mRetaining) {
            // mRetaining用于判读是否由于配置改变导致Fragment重建
            mViewModelStore.clear();
        }
    }
复制代码

ViewModel存储的数据不会在配置改变时而销毁, ViewModel是怎样保存的呢,看前面的分析在Fragment, FragmentActivity都有一个mViewModelStore的成员变量,只要保存好这个mViewModelStore这个就可以啦。当配置改变时,在onSaveInstanceState里保存数据,然后在onRestoreInstanceState恢复数据,但是这两个方法存储数据只能放在Bundle, 只能存小量数据, 过大会抛TransactionTooLargeException异常。所以不合适,看源码发现是利用Activity的onRetainNonConfigurationInstance()和getLastNonConfigurationInstance()。

   // FragmentActivity关键代码
	public final Object onRetainNonConfigurationInstance() {
        Object custom = onRetainCustomNonConfigurationInstance();
        // 这方法继承自Activty, 且把方法定义成final,不让子类实现,但是提供onRetainCustomNonConfigurationInstance方法
        FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
        //fragments是当前activity所有fragment需要保存的数据
        if (fragments == null && mViewModelStore == null && custom == null) {
            return null;
        }
        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.custom = custom;
        nci.viewModelStore = mViewModelStore;
        nci.fragments = fragments;
        // mViewModelStore 和 fragments 就存在NonConfigurationInstances里
        return nci;
    }

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        ...
        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        // 调用getLastNonConfigurationInstance方法获取NonConfigurationInstances恢复数据
        if (nc != null) {
            mViewModelStore = nc.viewModelStore;
        }
        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
            //nc.fragments通过mFragments.restoreAllState()恢复
        }
        ...
    }
复制代码

这里onRetainNonConfigurationInstance和getLastNonConfigurationInstance方法就不深入啦,配置改变时还想保存一些自定义object数据可以重写onRetainCustomNonConfigurationInstance去实现。那Fragment的mViewModelStore呢,就是mFragments.retainNestedNonConfig() 和 mFragments.restoreAllState() 这两个方法啦。 mFragments是FragmentController实例,最后是调用到FragmentManager, 而FragmentManager真正实现是FragmentManagerImpl。下面截取部分FragmentManagerImpl的关键代码。

// 这个方法就Activity里mFragments.retainNestedNonConfig()最终调用的方法
FragmentManagerNonConfig retainNonConfig() {
    setRetaining(mSavedNonConfig); // 由于篇幅的原因, 这个方法本文不展开了
    return mSavedNonConfig;
}
//来看mSavedNonConfig这个实例是在哪里创建的,回到FragmentActivity.onSaveInstanceState方法里发现调用mFragments.saveAllState()保存状态,最终来到FragmentManagerImpl的saveAllState()
Parcelable saveAllState() {
    mSavedNonConfig = null;
    saveNonConfig();
}    

void saveNonConfig() {
    ArrayList<Fragment> fragments = null;
    ArrayList<FragmentManagerNonConfig> childFragments = null;
    ArrayList<ViewModelStore> viewModelStores = null;
    if (mActive != null) {
        //mActive是SparseArray<Fragment>, 代表fragment栈, 遍历mActive,
        for (int i=0; i<mActive.size(); i++) {
            Fragment f = mActive.valueAt(i);
            if (f != null) {
                ...
                if (viewModelStores != null) {
                     // 把fragment的成员变量mViewModelStore添加到list中
                    viewModelStores.add(f.mViewModelStore);
                }
            }
        }
    }
    if (fragments == null && childFragments == null && viewModelStores == null) {
        mSavedNonConfig = null;
    } else {
        //viewModelStores存储到FragmentManagerNonConfig里
        mSavedNonConfig = new FragmentManagerNonConfig(fragments, childFragments,
                                                       viewModelStores);
    }
}
//mFragments.restoreAllState() 最终调用FragmentManagerImpl的restoreAllState()
void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
    if (state == null) return;
    FragmentManagerState fms = (FragmentManagerState)state;
    //fms是保存状态时存储在Parcelable的,现在拿出来恢复状态
    if (fms.mActive == null) return;
    //这里有很多种情况,这里大概分析常见的恢复过程
    ...
    mActive = new SparseArray<>(fms.mActive.length);
    //遍历FragmentState
    for (int i=0; i<fms.mActive.length; i++) {
        FragmentState fs = fms.mActive[i];
        if (fs != null) {
            ...
            ViewModelStore viewModelStore = null;
            if (viewModelStores != null && i < viewModelStores.size()) {
                viewModelStore = viewModelStores.get(i);
            }
            Fragment f = fs.instantiate(mHost, mContainer, mParent, childNonConfig,
                                        viewModelStore);
            // 传入viewModelStore, 调用instantiate方法重新生成Fragment
            if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
            mActive.put(f.mIndex, f);
        }
    }
}
复制代码

什么是LiveData, 以及工作原理

LiveData是一个可观察数据的持有者, 但是不像普通的可观察数据, LiveData是绑定了生命周期,例如activitie, fragment的生命周期。有点抽象, 还是先了解一下关键的类。

//Observer是一个接口,观察者。当数据改变时就回调onChanged
public interface Observer<T> {
    void onChanged(@Nullable T t);
}

//LiveData类是个抽象类,这里先看看有什么暴露出去的方法
public abstract class LiveData<T> {
    //添加观察者观察, 传入LifecycleOwner,用于来绑定生命周期
    public void observe(LifecycleOwner owner, Observer<T> observer)
    //添加观察者观察, 但是是没有LifecycleOwner
    public void observeForever(Observer<T> observer)
    //移除观察者
    public void removeObserver(Observer<T> observer)
    //移除某个LifecycleOwner里所有的观察者
    public void removeObservers(final LifecycleOwner owner)
    //是否有观察者
    public boolean hasObservers()
    //是否有活的观察者
    public boolean hasActiveObservers()
}
//MutableLiveData继承LiveData, 多开放2个方法。
public class MutableLiveData<T> extends LiveData<T> {
    public void postValue(T value) //post一个数据
    public void setValue(T value)  //设置一个数据
    //postValue和setValue的区别是:post可以在子线程用,而setValue只能在UI线程调用
}
复制代码

介绍完了主要的类,下面举个例子:

// 这段代码通常在Activity或者Fragment中, 用liveData去添加一个观察者
// AppCompatActivity或者Fragment已经LifecycleOwner,通常传this即可
// 当User数据有变化时,onChanged方法会被调用, 用于更新UI
liveData.observe(this, new Observer<User>() {
    @Override
    public void onChanged(@Nullable User user) {
    	//更新UI
    }
});

//下面这段代码通常在ViewModel中,这里liveData和上面代码的liveData是同一个
//可以通过postValue或者setValue去改成user数据, 有数据改变时, onChanged方法会被回调
//假如一个场景, 在ViewModel中,通过网络请求去拿user数据,然后postValue就会去通知UI层onChanged去更新UI
//liveData大概就是这个流程
liveData = new MutableLiveData<User>()
liveData.postValue(user)// 或者setValue(user)
复制代码

下面还是看看LiveData源码去了解一下原理

LiveData工作原理

这里以observe(LifecycleOwner owner, Observer observer) 和 postValue之间数据的通讯为例分析。对LifecycleOwner不熟悉的可以看我的上一篇文章:LifecycleOwner, 下面看LiveData.observe源码:


	@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
        //判断当前生命周期是DESTROYED, 立马return, 都销毁了,添加观察者没意义
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }

        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //LifecycleBoundObserver继承ObserverWrapper, LifecycleBoundObserver实现LifecycleOwner
        //mObservers这是一个Map, key是observer, value是ObserverWrapper
        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);
    }
复制代码

接着看LifecycleBoundObserver和ObserverWrapper片段:

    class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull final LifecycleOwner mOwner;

        @Override
        boolean shouldBeActive() {
            //至少是STARTED状态
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        //GenericLifecycleObserver继承自LifecycleObserver, 当生命周期改变时onStateChanged会被回调
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            //生命周期处于DESTROYED时, 移除观察者,mObserver是livedata.observe时传进来
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            //shouldBeActive()方法实现在当前类, 调用isAtLeast(STARTED), 至少是STARTED状态才是true
            //就是生命周期在STARTED和RESUME状态时, 才是true
            //接着调用了父类的activeStateChanged
            activeStateChanged(shouldBeActive());
        }
    }

    private abstract class ObserverWrapper {

        void activeStateChanged(boolean newActive) {
            // mActive状态相同立即返回
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we‘d never dispatch anything to inactive
            // owner
            mActive = newActive;
            //就是生命周期在STARTED和RESUME时, mActive为true, 其他为false
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            //当mActive=true时, mActiveCount会加1, 当mActive=false时, mActiveCount会减1。
            //这里为什么要加1和减1呢,结合Activity生命周期去考虑,当Activity.onCreate -> Activity.onStart -> Activity.onResume, State由CREATED->STARTED->RESUMED,这个过程当到STARTED时mActive为true,mActiveCount加1后为1, 接着RESUMED, mActive还是true, 这方法第一句(newActive == mActive)条件成立直接return, mActiveCount此时还是1。
            //当Activity.onResume->Activity.onPause->Activity.onStop,State由RESUMED->STARTED->CREATED, Activity.onStop后State为CREATED, isAtLeast(STARTED)就为false, 此时mActive=false, mActiveCount减1,mActiveCount为0啦。
            //当Activity.onStop->Activity.onStart->Activity.onResume, State由CREATED->STARTED->RESUMED, mActive为true,mActiveCount加1后为1, mActiveCount此时为1。
            if (wasInactive && mActive) {
                //根据上面一大段分析后,onActive会在Activity首次显示UI调用,从后台返回或者从另一个Activity回退后又调用一次。(打开透明Activity不走onStop,这种情况除外)
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                // Activity.onStop后调用
                onInactive();
            }
            if (mActive) {
                //分发数据, 跟踪dispatchingValue方法,会到LiveData.considerNotify方法
                dispatchingValue(this);
            }
        }
    }

    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            //mActive可以知道是否处于onStop状态, 是Stop状态就不要分发数据
            return;
        }
        if (!observer.shouldBeActive()) {
            //shouldBeActive()再次检查是否observer活着
            //ObserverWrapper的实现类不止LifecycleBoundObserver, 这里暂时没看懂为什么再次检查
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            //mVersion会在调用postValue()或者setValue()处+1
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
        调用onChanged分发改变的数据
    }
复制代码

接着看postValue方法是是如果把值传到onChanged里:


protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        // 一开始看到这里有点疑问,1. 为什么加锁, 1. 为什么要一个NOT_SET变量(NOT_SET是一个Obj对象)
        // 先带着疑问往下看
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) { // 先往下看,和加锁问题一起解释
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    // mPostValueRunnable运行在主线程
}

private final Runnable mPostValueRunnable = new Runnable() {
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {  //加锁, 和postValue里的锁是一样的
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        setValue((T) newValue);
    }
};  

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++; // 版本号加1,保证mVersion>mLastVersion
    mData = value; // 赋值给mData, 数据会分发到mObserver.onChanged
    dispatchingValue(null);

    //到这里很清晰啦,现在回头看看postValue和mPostValueRunnable里的锁,和NOT_SET的作用
    //1. postValue方法可能会被很多条线程调用
    //2. mPostValueRunnable异步运行在主线程, 主线程是串联执行的,一次执行一个runnable
    //3. 不加锁很明显不行, 多线程调用时, value从postValue方法赋值给mPendingData,
    //在mPostValueRunnable主线程里把mPendingData赋值给mData,
    //mPendingData和mData都是指向同一个对象, mData在主线程都是指向了最新的对象。
    //在主线程队列的里mPostValueRunnable每次运行都是拿了最新的数据,有点多余
    //4. 假如去掉NOT_SET, value从postValue方法赋值给mPendingData,
    // 再到setValue的mData, mPendingData和mData都是指向同一个对象,
    // 虽然加了锁也没用。但有了NOT_SET就不同啦, mPendingData地址给mData,NOT_SET地址给mPendingData,
    // 在postValue方法的子线程里新进来的value地址又赋值给mPendingData。
    //5.看回postValue方法里 if (!postTask) { return } 这个地方,
    // 假如A线程调用了postValue, 把value赋值给mPendingData并释放了锁,
    // 把A.mPostValueRunnable放到主线程的Message中,
    // 但这时之前的B.mPostValueRunnable还没运行完,运行到setValue方法,也没有持有锁。
    // 这时B线程也调用了postValue, 这时A.mPostValueRunnable还没运行,没有把mPendingData=NOT_SET,
    // B线程postTask就为false了, 接着又把value赋值给mPendingData, 接着就直接return。
    // 等A.mPostValueRunnable运行时, mPendingData又被B线程更新啦。
    // if (!postTask) { return } 这个判断能减少主线程没必要mPostValueRunnable运行,
    // 而且能更新到最新的数据。

}

private void dispatchingValue(@Nullable ObserverWrapper initiator) {
    // initiator是null , 下面是遍历mObservers存储ObserverWrapper通知所有观察者
    ...
    for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
         mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
        considerNotify(iterator.next().getValue());
        // considerNotify前面分析过了,看回LiveData.observe的过程, 最终分发数据Observer.onChanged
    }
}
复制代码

ViewModel和LiveData结合使用

先说说使用ViewModel和LiveData时注意事项:

  • ViewModel不要持有生命周期的对象,例如activity, fragment。最好context也不要持有
  • 可以使用AndroidViewModel具有application对象
  • activity, fragment不要拥有LiveData对象,LiveData最好保存在ViewModel里,ViewModel不会由于配置改变而销毁
  • activity, fragment也不要拥有数据对象,在Observer.onChange更新UI时,不要把数据存在activity, fragment中
public class UserActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        findViewById(R.id.btn_logout).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mViewModel.onLogout(); // 点击按钮退出登录
            }
        });
        mViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
        //ViewModelProviders是一个工具类,默认包含AndroidViewModelFactory把UserViewModel.class通过反射创建ViewModel并存储在Activity中
        mViewModel.getUserLiveData().observe(this, new Observer<User>() {
            @Override
            public void onChanged(@Nullable User user) {
            	//在观察者中更新UI
                if(user != null){
                    mTvName.setText(user.name);
                }else {
                    //没有登录的状态
                    mTvName.setText("用户还没登录!!!!!");
                }
            }
        });
        mViewModel.loadUserInfo();
    }
}

public class UserViewModel extends ViewModel {
	//userLiveData存储在UserViewModel
    private final MutableLiveData<User> userLiveData = new MutableLiveData<User>();
    public MutableLiveData<User> getUserLiveData() {
        return userLiveData;
    }
    @Override
    protected void onCleared() {
    	//释放资源
    }

    public void loadUserInfo() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ignored) {
                }
                //开启一个线程,异步操作,建议使用线程池,这里演示就直接new Thread
                User user = new User();
                user.name = "Albert";
                userLiveData.postValue(user); // 通知数据观察者
            }
        }).start();
    }

    public void onLogout() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ignored) {
                }
                /开启一个线程,异步操作
                userLiveData.postValue(null); // 通知数据观察者
            }
        }).start();
    }
}
复制代码

介绍完例子,下面说说优点:

  • 数据更新通知UI更新,数据的更新关联了生命周期,可以避免onStop时去更新UI.
  • 不需要手动处理生命周期
  • 没有内存泄漏
  • 配置更改,之前加载数据还能使用
  • 可以共享资源, 主要体现在同一个Activity里fragments可以共享viewmodel,livedata等(这里不展开,后面有空再分享)

参考:

原文地址:https://www.cnblogs.com/Free-Thinker/p/11496622.html

时间: 2024-08-30 15:58:41

Android Jetpack组件 - ViewModel,LiveData使用以及原理的相关文章

android 架构组件 - viewmodel

ViewModel类旨在以生命周期的方式存储和管理与ui相关的数据.ViewModel类允许数据在诸如屏幕旋转之类的配置更改中存活. 注意:要将ViewModel导入到您的Android项目中,请参见向您的项目添加组件. Android框架管理UI控制器的生命周期,比如activities和fragments.该框架可能会决定销毁或重新创建UI控制器,以响应完全超出您控制的某些用户操作或设备事件. 如果系统破坏或重新创建一个UI控制器,那么存储在其中的任何与UI相关的数据都将丢失.例如,你的应用

Android Jetpack让Android一飞冲天

背景介绍 早在2008年,Google 推出了Android ,但那个时候 Android 刚刚问世,经过这将近11年的发展和不断优化,Android 可以说逐渐变得成熟,方便和应用越来越广. 随着 Android 手机的市场保有量越来越多,APP的研发朝着愈发的简单化,易上手的方向发展.而 Google 也是站在这一个角度出发,如何快速得让一个研发人员开发出一款APP,也可以快速的添加新的开发人员. 现在在 Google 应用市场当中,大部分 APP 已经开始使用 Android Jetpac

带你了解Android Jetpack

1.Jetpack主要特性有以下三点: 1.加速开发组件可单独使用,也可以协同工作,当使用kotlin语言特性时,可以提高效率. 2.消除样板代码Android Jetpack可管理繁琐的Activity(如后台任务.导航和生命周期管理). 3.构建高质量的强大应用Android Jetpack组件围绕现代化设计实践构建而成,具有向后兼容性,可以减少崩溃和内存泄漏. 2.Jetpack的分类. DataBinding:以声明方式将可观察数据绑定到界面元素,通常和ViewModel配合使用.Lif

Android Jetpack架构组件:一文带你了解Lifecycle(使用篇)

前言 这一篇文章来介绍Android Jetpack架构组件的Lifecycle,Lifecycle用于帮助开发者管理Activity和Fragment 的生命周期,由于Lifecycle是LiveData和ViewModel的基础,所以需要先学习它. 1.为什么需要Lifecycle 在应用开发中,处理Activity或者Fragment组件的生命周期相关代码是必不可免的, 官方文档中举了一个例子,这里简化一下,在Activity中写一个监听,在Activity的不同生命周期方法中调用这个监听

Android 架构组件 之 ViewModel 学习

Overview 今天在学习的过程中,我学了一下Android的架构组件之ViewModel的学习操作.ViewModel也是属于我们的Android Jetpack的一部风. Android 开发者文档中是这么说的: ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据.ViewModel 类让数据可以在发生旋转等配置更改后继续存在的. 看一看我们是如何使用ViewModel的 架构组件为界面控制器提供了ViewModel 辅助程序类,该类负责为界面准备数据,在配置更改期间会

【Android】ViewModel+LiveData:更加直接地控制视图的方式

目录 LiveData 前言 使用ViewModel+LiveData LiveData 前言 ??ViewModel通过将UI data保存在ViewModel类实例的内部,从而大大地将MVC中的 Controller 与 View 分割开,并且通过ViewModel,我们可以较为方便地解决Activity生命周期发生改变(比如由屏幕旋转引起的生命周期重建)时,UI data的保存以及重现问题. ??下图展示了MVC中Controller与View的关系.简而言之就是,Controller负责

App 组件化/模块化之路——Android 框架组件(Android Architecture Components)使用指南

面对越来越复杂的 App 需求,Google 官方发布了Android 框架组件库(Android Architecture Components ).为开发者更好的开发 App 提供了非常好的样本.这个框架里的组件是配合 Android 组件生命周期的,所以它能够很好的规避组件生命周期管理的问题.今天我们就来看看这个库的使用. 通用的框架准则 官方建议在架构 App 的时候遵循以下两个准则: 关注分离 其中早期开发 App 最常见的做法是在 Activity 或者 Fragment 中写了大量

Android 四大组件之三(广播)

1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器).广播作为Android组件间的通信方式,可以使用的场景如下: 1.同一app内部的同一组件内的消息通信(单个或多个线程之间): 2.同一app内部的不同组件之间的消息通信(单个进程): 3.同一app具有多个进程的不同组件之间的消息通信: 4.不同app之间的组件之间消息通信: 5.Android系统在特定情况下与App之间的消息

【ALearning】第四章 Android Layout组件布局(一)

在本章中,我们将Android学习组件布局.在前面的章节,我们也开始使用LinearLayout布局.然后我们在布局文件更加具体的学习和理解,会. Android的界面是有布局和组件协同完毕的,布局好比是建筑里的框架,而组件则相当于建筑里的砖瓦.组件依照布局的要求依次排列.就组成了用户所看见的界面. Android的五大布局各自是LinearLayout(线性布局).FrameLayout(单帧布局).RelativeLayout(相对布局).AbsoluteLayout(绝对布局)和Table