Java教程

ViewModel 源码分析

本文主要是介绍ViewModel 源码分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

预备知识

Android中我知道Activity有一个onSaveInstanceState函数,用于在Activity在不幸被回收或者配置改变时存储序列化对象,在下次重建时onRestoreInstanceState取出序列化数据.
要是我们有非序列数据呢?

public Object onRetainNonConfigurationInstancepublic Object getLastNonConfigurationInstance()可以帮助我存储任意非序列化数据,用于下次重建复用对象

onRetainNonConfigurationInstance

class Activity
 public Object onRetainNonConfigurationInstance() {
        return null;
    }
}    

该函数在onStoponDestry之间回调,你可以返回任意对象,该对象会在下次重建Activity调用getLastNonConfigurationInstance获得.

我们看下一个demo:

class Person {

}

class MainActivity : Activity() {

  var myString: Person? = null
  private val TAG = "MainActivity"

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val lastNonConfigurationInstance = lastNonConfigurationInstance
    if (lastNonConfigurationInstance != null) {
      Log.e(TAG, "onCreate: lastNonConfigurationInstance hash:" + lastNonConfigurationInstance + "")
      myString = lastNonConfigurationInstance as Person

    }
    if (myString == null) {
      myString = Person()
    }

    Log.e(TAG, "onCreate: myString hash:" + myString + "")

  }

  override fun onRetainNonConfigurationInstance(): Person? {
    return myString
  }

  override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
  }

  override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
  }

}

输出

 onCreate: myString hash:com.example.leakstudy.Person@2b4aece1

进行旋转屏幕(Activity会重建)

//重建前
onCreate: myString hash:com.example.leakstudy.Person@2b4aece1
//重建后
onCreate: lastNonConfigurationInstance hash:com.example.leakstudy.Person@2b4aece1
onCreate: myString hash:com.example.leakstudy.Person@2b4aece1

而我们的viewmodel便是利用这一特性完成存储.

ViewModelStore的存储

ViewModelStoreOwner是一个重要的接口,且声明如下:

public interface ViewModelStoreOwner {
    @NonNull
    ViewModelStore getViewModelStore();
}

实现ViewModelStoreOwner接口的对象必须在configration改变时存储好自己ViewModelStore对象,并且在这个对象被回收时候调用ViewModelStoreonClear函数,而ComponentActivity对象便实现了这个接口.

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
                ViewModelStoreOwner,
       
       

我们在看一下ViewModelStore

public class ViewModelStore {
	//存储所有的viewModel,键为ViewModel的全类名.
    private final HashMap<String, ViewModel> mMap = new HashMap<>();
	//放一个新的viewmodel
    final void put(String key, ViewModel viewModel) {
        ViewModel oldViewModel = mMap.put(key, viewModel);
        //如果存在旧元素那么调用oncreard
        if (oldViewModel != null) {
            oldViewModel.onCleared();
        }
    }

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

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

    /**
     *  调用所有的viewmodel 的clear函数
     */
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }
}

我们继续研究ComponentActivity的实现

//ComponentActivity.java
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        ViewModelStoreOwner{
	 static final class NonConfigurationInstances {
        Object custom;
        ViewModelStore viewModelStore;
    }
    
    private ViewModelStore mViewModelStore;
	NonConfigurationInstances mLastNonConfigurationInstances;

	//activity在回收或者改变时configration存储数据
    public final Object onRetainNonConfigurationInstance() {
        Object custom = onRetainCustomNonConfigurationInstance();
		//将viewmodel存储到NonConfigurationInstances对象中
        ViewModelStore viewModelStore = mViewModelStore;
        
        if (viewModelStore == null) {
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                viewModelStore = nc.viewModelStore;
            }
        }
		
        if (viewModelStore == null && custom == null) {
            return null;
        }

        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.custom = custom;
        nci.viewModelStore = viewModelStore;
        return nci;
    }

	//我们看下如何返回viewmodel
	@Override
    public ViewModelStore getViewModelStore() {
       
        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;
    }
    

}

我们知道viewmodel会在activity被意外非回收销毁时会调用Viewmodel.onCleared函数,而Viewmodel.onCleared是被mViewModelStore.clear回调的.但是我们需要区分调用Destroy是否需要考虑复用的情况,也是正常销毁还是回收在售后重建.

 public ComponentActivity() {
 	 Lifecycle lifecycle = getLifecycle();
	 getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                    //on_Destroy的根据是否是配置改变确定是否需要调用clear函数
                if (event == Lifecycle.Event.ON_DESTROY) {
                    if (!isChangingConfigurations()) {
                        getViewModelStore().clear();
                    }
                }
            }
        });
    //mChangingConfigurations会在onstop时候进行判断    
    public boolean isChangingConfigurations() {
    	//mChangingConfigurations位于activity
        return mChangingConfigurations;
    }    
 }

ViewModel的创建

class MainActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val viewModelProvider = ViewModelProvider(this, AndroidViewModelFactory(this.application))
    val viewModel = viewModelProvider.get(MyViewModel::class.java)

    println("MainActivity.onCreate")

  }

}
//ViewModelProvider.java
public class ViewModelProvider {
	 public interface Factory {
        <T extends ViewModel> T create(@NonNull Class<T> modelClass);
    }
}
public class ViewModelProvider {
	    private final Factory mFactory;
	    private final ViewModelStore mViewModelStore;
		public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {
        	this(owner.getViewModelStore(), factory);
    	}
    	public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
        	mFactory = factory;
        	mViewModelStore = store;
   		}
   		//获取viewmodel实例
		public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
        	String canonicalName = modelClass.getCanonicalName();
       
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }
     //最终调用这
     public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
        //如果mViewModelStore没有存储这个viewmodel,将返回null
        ViewModel viewModel = mViewModelStore.get(key);
		//model有可能是空,如果是空必然返回false
        if (modelClass.isInstance(viewModel)) {
            return (T) viewModel;
        } else {
            //预留代码
            if (viewModel != null) {
            
            }
        }
        //判断传入的factory类型,我们这里直接看false即可
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
        } else {
        	//调用factory.create完成viewmodel
            viewModel = (mFactory).create(modelClass);
        }
        //将创建的viewimodel放入mViewModelStore
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }
}

我们最后看一个库里一个默认实现AndroidViewModelFactory.

    public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {

        private static AndroidViewModelFactory sInstance;

     
        @NonNull
        public static AndroidViewModelFactory getInstance(@NonNull Application application) {
            if (sInstance == null) {
                sInstance = new AndroidViewModelFactory(application);
            }
            return sInstance;
        }

        private Application mApplication;

      
        public AndroidViewModelFactory(@NonNull Application application) {
            mApplication = application;
        }

        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        	//当前modelClass类是AndroidViewModel或者父类
            if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
                try {
                	//返回新的实例对象
                    return modelClass.getConstructor(Application.class).newInstance(mApplication);
                } catch (NoSuchMethodException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                } catch (InstantiationException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                } catch (InvocationTargetException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                }
            }
            //super.create是利用空构造函数实现的
            return super.create(modelClass);
        }
    }

viewmodel整体比较简单.

这篇关于ViewModel 源码分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!