ViewModel+LiveData总结

ViewMode+LiveData总结

Activity/Fragment只应关注UI,而不应关系操作逻辑,因此操作逻辑应放到Viewmodel中去
下面是我手画的数据流图:
ViewModel+LiveData总结_第1张图片
首先有FragmentViewModelLivedata这三个对象。

  1. Fragment观察Viewmodel的Livedata数据,如果livedata的值改变会通知Frament。
  2. ViewModel获取数据(网络、数据库),然后设置Livedata的值
  3. Livedata的值改变就通知Fragment
  4. Fragment刷新界面

代码如下:
Fragment


import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;

/**
*
* @date 2020/9/19
*/
public class MyActivity extends AppCompatActivity {
   Handler messageHandler;
   MyViewModel myViewModel;
   Handler mainHandler;

   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       final TextView textView = findViewById(R.id.textView);
       // 新建ViewModel
       myViewModel = new MyViewModel();

       // 子线程
       HandlerThread handlerThread = new HandlerThread("");
       handlerThread.start();
       // 子线程Handler
       messageHandler = new Handler(handlerThread.getLooper());
       // 主线程handler
       mainHandler = new Handler(getMainLooper());
       // 开启自自线程改变数据
       messageHandler.post(new Runnable() {
           @Override
           public void run() {
               int i = 0;
               while (i < 100) {
                   mainHandler.post(new Runnable() {
                       @Override
                       public void run() {
                           myViewModel.requestChangeText();
                       }
                   });
                   try {
                       Thread.sleep(500);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   i++;
               }
           }
       });

       myViewModel.getmText().observe(this, new Observer() {
           @Override
           public void onChanged(final String s) {
               runOnUiThread(new Runnable() {
                   @Override
                   public void run() {
                       textView.setText(s);
                   }
               });

           }
       });
   }
}

viewmodel


import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import java.util.Observable;
import java.util.Random;

/**
 * Describe:

* 描述:

* * @date 2020/9/19 */ public class MyViewModel extends ViewModel implements IMyModelHelper { private MutableLiveData mText = new MutableLiveData(); public MyViewModel() { } public MutableLiveData getmText() { return mText; } @Override public void requestChangeText() { changeText(); } private void changeText(){ getmText().setValue(new Random(10).toString()); } }
package com.loyal888.tets;

/**
 * Describe:

* 描述:

* * @date 2020/9/19 */
public interface IMyModelHelper { void requestChangeText(); }

总结:数据通知可以使用Observer,实现进一步解耦合

MVP 和MVVM的区别

ViewModel+LiveData总结_第2张图片

获取VidewModel实例

// 新建ViewModel
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);

VideoModel的生命周期

系统首次调用 Activity 对象的 onCreate() 方法时请求 ViewModel。系统可能会在 Activity 的整个生命周期内多次调用 onCreate(),如在旋转设备屏幕时。ViewModel 存在的时间范围是从您首次请求 ViewModel 直到 Activity 完成并销毁。

在当前生命周期为Destrory的时候,清除了mViewModelStore
ViewModel+LiveData总结_第3张图片

ViewModel中使用Context

扩展AndroidViewModel

ViewModel 对象可以包含 LifecycleObservers,如 LiveData 对象。但是,ViewModel 对象绝不能观察对生命周期感知型可观察对象(如 LiveData 对象)的更改。 如果 ViewModel 需要 Application 上下文(例如,为了查找系统服务),它可以扩展 AndroidViewModel 类并设置用于接收 Application 的构造函数,因为 Application 类会扩展 Context。

ViewModel源码分析

1. ViewModelProvider.of(this)

  • 检查应用的上下文
  • 构造了AndroidViewModelFactory
  • 返回provider
   public static ViewModelProvider of(@NonNull FragmentActivity activity) {
        return of(activity, null);
    }
    
    @NonNull
    @MainThread
    public static ViewModelProvider of(@NonNull FragmentActivity activity,
            @Nullable Factory factory) {
        // 1. 检查应用的上下文且必须是application
        Application application = checkApplication(activity);
        if (factory == null) {
        // 2.构造了AndroidViewModelFactory
            factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
        }
        // 3.返回provider
        // 3.1 注意这里的activity.getViewModelStore()
        return new ViewModelProvider(activity.getViewModelStore(), factory);
    }

2. activity.getViewModelStore()

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) {
           	// 获取上一次配置改变保存的NonConfigurationInstances,比如屏幕旋转
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                // Restore the ViewModelStore from NonConfigurationInstances
                // 配置改变,viewModelStore不空,直接使用
                // 这个viewModelStore是在哪里保存的?见下文
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                // 第一次来就新建一个ViewModelStore,保存的上一次的状态
                // 新建来之后保存到哪里?见下文
                mViewModelStore = new ViewModelStore();
            }
        }
        return mViewModelStore;
    }

3.保存ViewModelStore

getLastNonConfigurationInstance();
保存呢? 调用的是ConponentActivity中的onRetainNonConfigurationInstance,调用时机介于onStoponDestroy中间,onSaveInstance之后。

public final Object onRetainNonConfigurationInstance() {
       Object custom = onRetainCustomNonConfigurationInstance();
   	// 这里就是上文的new出来的mViewModelStore
       ViewModelStore viewModelStore = mViewModelStore;
       if (viewModelStore == null) {
           // No one called getViewModelStore(), so see if there was an existing
           // ViewModelStore from our last NonConfigurationInstance
           NonConfigurationInstances nc =
                   (NonConfigurationInstances) getLastNonConfigurationInstance();
           if (nc != null) {
               viewModelStore = nc.viewModelStore;
           }
       }

       if (viewModelStore == null && custom == null) {
           return null;
       }

       NonConfigurationInstances nci = new NonConfigurationInstances();
       nci.custom = custom;
       // 把mViewModelStore保存到NonConfigurationInstances中去
       nci.viewModelStore = viewModelStore;
       return nci;
   }

4. 获取上一次保存的viewmodel

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) {
           NonConfigurationInstances nc =
                   (NonConfigurationInstances) getLastNonConfigurationInstance();
           if (nc != null) {
           
               // Restore the ViewModelStore from NonConfigurationInstances
               //  注意上面这句英文
               mViewModelStore = nc.viewModelStore;
           }
           if (mViewModelStore == null) {
               mViewModelStore = new ViewModelStore();
           }
       }
       return mViewModelStore;
   }

5. 获取ViewModel
ViewModelProviders.of(this).get(MyViewModel.class);

public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
      String canonicalName = modelClass.getCanonicalName();
      if (canonicalName == null) {
          throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
      }
      return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
  }
  
  public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
  // 上文提到构建出来的mViewModelStore,从HashMap取出实例
      ViewModel viewModel = mViewModelStore.get(key);

      if (modelClass.isInstance(viewModel)) {
          //noinspection unchecked
          // 	有就返回
          return (T) viewModel;
      } else {
          //noinspection StatementWithEmptyBody
          if (viewModel != null) {
              // TODO: log a warning.
          }
      }
      if (mFactory instanceof KeyedFactory) {
          viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
      } else {
      	// 没有反射创建出来
          viewModel = (mFactory).create(modelClass);
      }
      // 将mViewModelStore保存到HashMap,保存的时候会销毁旧对象
      mViewModelStore.put(key, viewModel);
      //noinspection unchecked
      return (T) viewModel;
  }
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) {
       	// 旧viewmodel会被清除!!!
           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();
   }
}

总结: VieModelStore存在于FragmentActivity中,在配置更改导致Activity销毁前通过onRetainNonConfiguraionInstance将数据对象保存,并在重建时通过getLastNonConfigurationInstance将数据还原回来,从而保证了Activity内ViewModelStore 的唯一性一致性

LiveData

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

源码分析

构造方法

 public LiveData(T value) {
 		// 保存具体的值
        mData = value;
        // 当前版本
        mVersion = START_VERSION + 1;
    }
}

观察Livedata

 myViewModel.getmText().observe(this, new Observer<String>() {
            @Override
            public void onChanged(final String s) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText(s);
                    }
                });

            }
        });

observe了什么

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);
       // mObservers 添加了当前观察者
        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);
    }

数据改变setValue之后

 protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

   void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                        // 通知并回调每一个观察者的回调方法
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }  

Transformations#map()

eg:

public static <X, Y> LiveData<Y> map(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, Y> mapFunction) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        // X改变了,Y继续
        result.addSource(source, new Observer<X>() {
            @Override
            public void onChanged(@Nullable X x) {
                result.setValue(mapFunction.apply(x));
            }
        });
        return result;
    }

Transtormations#switchMap

 MutableLiveData userIdLiveData = ...;
 LiveData userLiveData = Transformations.switchMap(userIdLiveData, id ->
     repository.getUserById(id));

 void setUserId(String userId) {
      this.userIdLiveData.setValue(userId);
 }

总结,使用ViewModel和LiveData的优势

1 不需要手动处理生命周期
ViewModel和LiveData本身是生命周期可感知的

2 确保View可以及时拿到数据状态

LiveData遵循观察者模式,数据更改时,LiveData会通知对象。这也是它的优势,如果UI改变很多,MVP就需要写很多的接口。View被动的接受Presenter的指令。

3 减少内存泄漏

LiveData绑定了Lifecycle对象,ViewModel 在生命周期方法中自行清理回收

4 共享资源
单例使用ViewModel和LiveData,可以在程序中共享他们,例两个fragment共享一个ViewModel

1、建议添加LiveData和ViewModel的详细使用介绍,方便大家知道一些高级使用方式。比如LiveData对数据的拼装等。

2、文档不太能体现出和MVP的对比及优势。比如ViewModel和View解耦之类的。

你可能感兴趣的:(android,android)