FragmentContainerView
FragmentContainerView继续自FrameLayout, 可以动态添加FrameLayout 支持android:name 和 android: tag属性。
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/fragment_container_view" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.example.MyFragment" android:tag="my_tag"> </androidx.fragment.app.FragmentContainerView>ViewModel创建和存储数据
Lifecycle、ViewModel、SaveState集成,通过by ViewModels ,by activityViewModels,ViewModelProvider构造函数,ViewmodelProvider.of与Fragment一起利用时,默认利用SaveStateViewModelFactory。这个类的重要功能可以关联一个SavedStateHandle,先看下创建ViewModel的方式,再看下SaveStateViewModelFactory和SavedStateHandle。
1、在fragment中创建ViewModel
class MyFragment : Fragment() { val viewmodel: MyViewModel by viewmodels() }@MainThreadpublic inline fun <reified VM : ViewModel> Fragment.viewModels( noinline ownerProducer: () -> ViewModelStoreOwner = { this }, noinline factoryProducer: (() -> Factory)? = null): Lazy<VM> = createViewModelLazy( VM::class, { ownerProducer().viewModelStore }, factoryProducer ?: { (ownerProducer() as? HasDefaultViewModelProviderFactory)?.defaultViewModelProviderFactory ?: defaultViewModelProviderFactory })2、在fragment中创建ViewModel
class MyFragment : Fragment() { val viewmodel: MyViewModel by activityViewModels() }@MainThreadpublic inline fun <reified VM : ViewModel> Fragment.activityViewModels( noinline factoryProducer: (() -> Factory)? = null): Lazy<VM> = createViewModelLazy( VM::class, { requireActivity().viewModelStore }, factoryProducer ?: { requireActivity().defaultViewModelProviderFactory })3、在activity中创建ViewModel
class MyComponentActivity : ComponentActivity() { val viewmodel: MyViewModel by viewmodels() }public inline fun <reified VM : ViewModel> ComponentActivity.viewModels( noinline factoryProducer: (() -> Factory)? = null): Lazy<VM> { val factoryPromise = factoryProducer ?: { defaultViewModelProviderFactory } return ViewModelLazy(VM::class, { viewModelStore }, factoryPromise)}4、各自类中创建ViewModel
ViewModelProvider(this).get(TestViewModel::class.java)public ViewModelProvider(@NonNull ViewModelStoreOwner owner) { this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory() : NewInstanceFactory.getInstance()); } fun getDefaultViewModelProviderFactory(): ViewModelProvider.Factory? { if (mDefaultFactory == null) { mDefaultFactory = SavedStateViewModelFactory( application, this, getArguments()) } return mDefaultFactory }上述1,2,3终极也会调用到4这种方式实现的。可以看到新版本利用了
SavedStateViewModelFactory方式创建ViewModel,看下创建过程。
public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) { boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass); Constructor<T> constructor; if (isAndroidViewModel && mApplication != null) { constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE); } else { constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE); } // doesn't need SavedStateHandle if (constructor == null) { return mFactory.create(modelClass); } SavedStateHandleController controller = SavedStateHandleController.create( mSavedStateRegistry, mLifecycle, key, mDefaultArgs); try { T viewmodel; if (isAndroidViewModel && mApplication != null) { viewmodel = constructor.newInstance(mApplication, controller.getHandle()); } else { viewmodel = constructor.newInstance(controller.getHandle()); } viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller); return viewmodel; } catch (IllegalAccessException e) { throw new RuntimeException("Failed to access " + modelClass, e); } }可以看到假如传入modelClass的构造参数没有SavedStateHandle,则默认Factory(NewInstanceFactory)创建ViewModel。SavedStateHandle 是做什么的了?
先看下Fragment中数据保存。
5、Fragment数据保存
void performSaveInstanceState(Bundle outState) { onSaveInstanceState(outState); mSavedStateRegistryController.performSave(outState); Parcelable p = mChildFragmentManager.saveAllStateInternal(); if (p != null) { outState.putParcelable(FragmentManager.SAVED_STATE_TAG, p); } }FragmentStateManager,当状态改变,实行saveState,然后实行了performSaveInstanceState方法。
可以看到保存数据,先实行了onSaveInstanceState,再实行了
mSavedStateRegistryController.performSave(outState),也就是我们自界说的存储是在Fragment之后的。然后看下performSave中的实行。
void performSave(@NonNull Bundle outBundle) { Bundle components = new Bundle(); if (mRestoredState != null) { components.putAll(mRestoredState); } for (Iterator<Map.Entry<String, SavedStateProvider>> it = mComponents.iteratorWithAdditions(); it.hasNext(); ) { Map.Entry<String, SavedStateProvider> entry1 = it.next(); components.putBundle(entry1.getKey(), entry1.getValue().saveState()); } outBundle.putBundle(SAVED_COMPONENTS_KEY, components); }可以看到 components存储了全部通过SavedStateProvider方法返回的Bundle。这个components是通过什么方式存的了?
public void registerSavedStateProvider(@NonNull String key, @NonNull SavedStateRegistry.SavedStateProvider provider) { SavedStateRegistry.SavedStateProvider previous = mComponents.putIfAbsent(key, provider); }1、components中的SavedStateProvider是通过registerSavedStateProvider添加进来。在frgament和activity中利用:
fun testSave() { savedStateRegistry.registerSavedStateProvider(TAG) { var bundle = Bundle() bundle.putString("data", "数据") Log.d(TAG, " Save: 保存 " + lifecycle.currentState.name) bundle } } fun testRestore() { var consumeRestoredStateForKey = savedStateRegistry.consumeRestoredStateForKey(TAG) Log.d(TAG, "restore: 规复 " + consumeRestoredStateForKey?.get("data") + " " + lifecycle.currentState.name) }2、在SavedStateHandleController中也调用了registerSavedStateProvider,而这个SavedStateHandleController的getHandle()就是创建ViewModel的构造函数参数。
void attachToLifecycle(SavedStateRegistry registry, Lifecycle lifecycle) { if (mIsAttached) { throw new IllegalStateException("Already attached to lifecycleOwner"); } mIsAttached = true; lifecycle.addObserver(this); registry.registerSavedStateProvider(mKey, mHandle.savedStateProvider()); }这个方法在创建ViewModel时和屏幕旋转从ViewModelStore中得到ViewModel时调用,包管 registry.registerSavedStateProvider。
上面的mHandle 就是 SavedStateHandle。而且提供了一个savedStateProvider用来获取Bundle。看下这个provider
private final SavedStateProvider mSavedStateProvider = new SavedStateProvider() { @SuppressWarnings("unchecked") @NonNull @Override public Bundle saveState() { // Get the saved state from each SavedStateProvider registered with this // SavedStateHandle, iterating through a copy to avoid re-entrance Map<String, SavedStateProvider> map = new HashMap<>(mSavedStateProviders); for (Map.Entry<String, SavedStateProvider> entry : map.entrySet()) { Bundle savedState = entry.getValue().saveState(); set(entry.getKey(), savedState); } // Convert the Map of current values into a Bundle Set<String> keySet = mRegular.keySet(); ArrayList keys = new ArrayList(keySet.size()); ArrayList value = new ArrayList(keys.size()); for (String key : keySet) { keys.add(key); value.add(mRegular.get(key)); } Bundle res = new Bundle(); // "parcelable" arraylists - lol res.putParcelableArrayList("keys", keys); res.putParcelableArrayList("values", value); return res; } };可以看到这个类在提供Bundle之前,将原始数据转化成Bundle。那么利用者怎样把数据给这个SavedStateHandle了? 看下这个类提供的方法和利用:
1、第一种方式 : 自动存Bundle对象。
class TestViewModel1 : ViewModel { private val TAG = "TestViewModel1" private var handle: SavedStateHandle? = null constructor(handle: SavedStateHandle) { this.handle = handle } fun testResore() { var bundle = handle?.get<Bundle>("mahao") var age = bundle?.getString("age") Log.d(TAG, "testResore: " + age) var liveData = handle?.getLiveData<Bundle>("mahao") Log.d(TAG, "testResore: >>>> " + liveData?.value?.get("age")) liveData?.observeForever { var stringAge = it.get("age") Log.d(TAG, "testResore: ----- " + stringAge) } } fun testSave() { handle?.setSavedStateProvider("mahao", object : SavedStateRegistry.SavedStateProvider { override fun saveState(): Bundle { var bundle = Bundle() bundle.putString("age", "27") Log.d(TAG, "saveState: viewmodel 数据保存了") return bundle } }) } fun testModify() { var liveData = handle?.getLiveData<Bundle>("mahao") var bundle = Bundle() bundle.putString("age", "23") liveData?.postValue(bundle) }}向该类提供数据也是利用的SavedStateProvider 。通报该类后,当数据保存时,将改数据转成Map存储在内存中,规复数据的时间可以通过
handle.get(key) 和 handle?.getLiveData<Bundle>(key) 获取bundle。
2、第二种方式:恣意对象
上面自动通过bundle保存,还可以通过SavingStateLiveData保存,由于mRegular中记录了key,存储就根据key值来存储的。
@Override public void setValue(T value) { if (mHandle != null) { mHandle.mRegular.put(mKey, value); } super.setValue(value); }以是创建一个SavingStateLiveData对象,而且调用记录key。
constructor(handle: SavedStateHandle) { this.handle = handle initData() } fun initData() { liveData = handle?.getLiveData<String>("key", "1223") liveData?.value = "1224" var myValue = handle?.get<String>("key") Log.d(TAG, ": key = " + myValue) }FramentManager弃用API
弃用了getFragmentManager,requireFragmentManager ,利用getParentFragmentManager。假如fragment没有添加,则会抛出非常,可以利用isAdded()判断。
public final FragmentManager getParentFragmentManager() { FragmentManager fragmentManager = mFragmentManager; if (fragmentManager == null) { throw new IllegalStateException( "Fragment " + this + " not associated with a fragment manager."); } return fragmentManager; } if (this.isAdded) { parentFragmentManager }ViewTree中支持API
获取LifecycleOwner、ViewModelStoreOwner savedStateRegistryOwner
init { var findViewTreeLifecycleOwner = findViewTreeLifecycleOwner() var lifecyclerOwner = ViewTreeLifecycleOwner.get(this) lifecyclerOwner?.lifecycle?.addObserver(object : LifecycleEventObserver { override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { } }) var viewModelStoreOwner = ViewTreeViewModelStoreOwner.get(this) var viewModel1 = ViewModelProvider(viewModelStoreOwner!!).get(TestViewModel1::class.java) viewModel1.testSave() var savedStateRegistryOwner = ViewTreeSavedStateRegistryOwner.get(this) savedStateRegistryOwner?.savedStateRegistry?.registerSavedStateProvider(TAG, object : SavedStateRegistry.SavedStateProvider { override fun saveState(): Bundle { var bundle = Bundle() bundle.putString("name", "haha") return bundle; } }) }Activity Result API
Activity Result API 提供了用于注册result、启动result以及在体系分派result后对其进行处理惩罚的组件。
registerForActivityResult(StartActivityForResult(), ActivityResultCallback<ActivityResult> { result -> if (result.getResultCode() === RESULT_OK) { val intent: Intent = result.data!! } })registerForActivityResult = fragmentOne!!.registerForActivityResult(object : ActivityResultContract<String, String>() { override fun createIntent(context: Context, input: String?): Intent { var intent = Intent(context, MainActivity::class.java) intent.putExtra("name", input) return intent } override fun getSynchronousResult(context: Context, input: String?): SynchronousResult<String>? { if (input.equals("age")) { return SynchronousResult("27") } return super.getSynchronousResult(context, input) } override fun parseResult(resultCode: Int, intent: Intent?): String { return "zhangsan" } } /*, object : ActivityResultRegistry() { override fun <I : Any?, O : Any?> onLaunch(requestCode: Int, contract: ActivityResultContract<I, O>, input: I, options: ActivityOptionsCompat?) { Log.d(TAG, "onLaunch: " + requestCode + " " + " " + input) // ActivityCompat.startActivityForResult(this@FragmentContainerActivity, intent, requestCode, null) dispatchResult(requestCode, expectedResult) } }*/, activityResultRegistry, object : ActivityResultCallback<String> { override fun onActivityResult(result: String?) { Log.d(TAG, "onActivityResult: 1 " + result) } })//启动registerForActivityResult?.launch("aaa1")假如上述不利用activityResultRegistry,创建一个对象,我们须要利用 dispatchResult(requestCode, expectedResult) 通报给ActivityResultCallback,看下完备的调用过程。
调用registerForActivityResult?.launch("aaa1") 终极调用到 ComponentActivity类中
private final ActivityResultRegistry mActivityResultRegistry = new ActivityResultRegistry() { @Override public <I, O> void onLaunch( final int requestCode, @NonNull ActivityResultContract<I, O> contract, I input, @Nullable ActivityOptionsCompat options) { ComponentActivity activity = ComponentActivity.this; final ActivityResultContract.SynchronousResult<O> synchronousResult = contract.getSynchronousResult(activity, input); if (synchronousResult != null) { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { dispatchResult(requestCode, synchronousResult.getValue()); } }); return; } // Start activity path Intent intent = contract.createIntent(activity, input); Bundle optionsBundle = null; if (ACTION_REQUEST_PERMISSIONS.equals(intent.getAction())) { // requestPermissions path String[] permissions = intent.getStringArrayExtra(EXTRA_PERMISSIONS); if (permissions == null) { permissions = new String[0]; } ActivityCompat.requestPermissions(activity, permissions, requestCode); } else { // startActivityForResult path ActivityCompat.startActivityForResult(activity, intent, requestCode, optionsBundle); } } };上面看到终极调用startActivityForResult , requestPermissions,那么数据返回肯定也是通过mActivityResultRegistry处理惩罚。
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (!mActivityResultRegistry.dispatchResult(requestCode, resultCode, data)) { super.onActivityResult(requestCode, resultCode, data); } }接下来就是回调给callback
private <O> void doDispatch(String key, int resultCode, @Nullable Intent data, @Nullable CallbackAndContract<O> callbackAndContract) { if (callbackAndContract != null && callbackAndContract.mCallback != null) { ActivityResultCallback<O> callback = callbackAndContract.mCallback; ActivityResultContract<?, O> contract = callbackAndContract.mContract; callback.onActivityResult(contract.parseResult(resultCode, data)); } else { mParsedPendingResults.remove(key); mPendingResults.putParcelable(key, new ActivityResult(resultCode, data)); } }可以看到上述callbackAndContract大概为null,这是由于在注册的监听的时间ActivityResultRegistry的这个register参数差异导致,看下注册的代码。
public final <I, O> ActivityResultLauncher<I> register( @NonNull final String key, @NonNull final LifecycleOwner lifecycleOwner, @NonNull final ActivityResultContract<I, O> contract, @NonNull final ActivityResultCallback<O> callback) { Lifecycle lifecycle = lifecycleOwner.getLifecycle(); if (lifecycle.getCurrentState().isAtLeast(Lifecycle.State.STARTED)) { throw new IllegalStateException("LifecycleOwner " + lifecycleOwner + " is " + "attempting to register while current state is " + lifecycle.getCurrentState() + ". LifecycleOwners must call register before " + "they are STARTED."); } final int requestCode = registerKey(key); LifecycleContainer lifecycleContainer = mKeyToLifecycleContainers.get(key); if (lifecycleContainer == null) { lifecycleContainer = new LifecycleContainer(lifecycle); } LifecycleEventObserver observer = new LifecycleEventObserver() { @Override public void onStateChanged( @NonNull LifecycleOwner lifecycleOwner, @NonNull Lifecycle.Event event) { if (Lifecycle.Event.ON_START.equals(event)) { mKeyToCallback.put(key, new CallbackAndContract<>(callback, contract)); if (mParsedPendingResults.containsKey(key)) { @SuppressWarnings("unchecked") final O parsedPendingResult = (O) mParsedPendingResults.get(key); mParsedPendingResults.remove(key); callback.onActivityResult(parsedPendingResult); } final ActivityResult pendingResult = mPendingResults.getParcelable(key); if (pendingResult != null) { mPendingResults.remove(key); callback.onActivityResult(contract.parseResult( pendingResult.getResultCode(), pendingResult.getData())); } } else if (Lifecycle.Event.ON_STOP.equals(event)) { mKeyToCallback.remove(key); } else if (Lifecycle.Event.ON_DESTROY.equals(event)) { unregister(key); } } }; lifecycleContainer.addObserver(observer); mKeyToLifecycleContainers.put(key, lifecycleContainer); return new ActivityResultLauncher<I>() { @Override public void launch(I input, @Nullable ActivityOptionsCompat options) { mLaunchedKeys.add(key); Integer innerCode = mKeyToRc.get(key); onLaunch((innerCode != null) ? innerCode : requestCode, contract, input, options); } @Override public void unregister() { ActivityResultRegistry.this.unregister(key); } @NonNull @Override public ActivityResultContract<I, ?> getContract() { return contract; } }; }上述代码
1、假如参数有lifecyclerOwner,注册必须在OnStart之前。
2、注册register,假如参数有lifecyclerOwner,则Lifecycle.Event.ON_START状态时,才从pendingResult中取出数据。
3、 mKeyToCallback.put(key, new CallbackAndContract<>(callback, contract)); 这个方法为什么添加在这里?假如当前页面没有跳转,也能通过activityResultRegistry.dispatchResult回调数据给callback。
4、注册register,假如参数有lifecyclerOwner,则ActivityResultLauncher会在onDestroy时unregister。
总结: 由于Activity Result API 的封装,提供了多种Intent, 更方便在activity和fragment中启动activity,更加解耦,支持在单独的类中处理惩罚Activity的返回效果(须要通报activityResultRegistry)。 |