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()
}
@MainThread
public 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()
}
@MainThread
public 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)。
网友评论