Fragment版本变革

源码 2024-9-10 06:45:02 91 0 来自 中国
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)。
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-23 20:19, Processed in 0.170650 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表