如何避免通过FragmentManager重新创建片段?

问题描述 投票:0回答:1

我正在使用TabLayout和两个表示标签内容的片段进行活动。我在活动的OnCreate方法中手动管理打开的选项卡的当前状态:

import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;

import com.google.android.material.tabs.TabLayout;

public class LoginActivity extends AppCompatActivity {

    private TabLayout tabLayout;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        tabLayout = findViewById(R.id.tabLayout);

        //initialize or restore opened tab, after activity first started or recreated
        int tabIndex = savedInstanceState == null ? 0 : savedInstanceState.getInt("tabIndex");
        Fragment f;
        switch (tabIndex) {
            case 0:
                f = new SignInFragment();
                break;
            case 1:
                f = new SignUpFragment();
                break;
            default:
                throw new UnsupportedOperationException();
        }
        //sync tab indicator
        tabLayout.selectTab(tabLayout.getTabAt(tabIndex));
        //set opened fragment
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.tabContent, f)
                .commit();

        //add listener to handle tab switching
        tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                Fragment tabFragment;
                switch (tab.getPosition()) {
                    case 0:
                        tabFragment = new SignInFragment();
                        break;
                    case 1:
                        tabFragment = new SignUpFragment();
                        break;
                    default:
                        throw new UnsupportedOperationException();
                }
                getSupportFragmentManager().beginTransaction()
                        .setCustomAnimations(com.google.android.material.R.anim.abc_grow_fade_in_from_bottom, com.google.android.material.R.anim.abc_shrink_fade_out_from_bottom)
                        .replace(R.id.tabContent, tabFragment)
                        .commit();
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tabIndex", tabLayout.getTabAt(tabLayout.getSelectedTabPosition()).getPosition());
    }
}

这只是简单的示例。我用C#编写的真实代码,并具有一些其他逻辑来存储和管理活动重启之间的状态。

配置更改时的问题(例如,开关方向):

  1. 打开的片段被破坏
  2. 活动被破坏
  3. 重新启动活动
  4. 在onCreate方法中,当调用super.onCreate(savedInstanceState)片段管理器时,使用默认(无参数)构造函数重新创建片段(在步骤1中销毁)。
  5. 我的onCreate方法中的代码恢复被破坏的片段。因此,由片段管理器重新创建的片段被销毁并替换为在此步骤中创建的片段。

如何避免这种行为?我不需要片段管理器还原的片段。另外,我不需要片段的默认构造函数(我有一些自定义ViewModel通过托管活动的构造函数注入到片段中)

将null放入super.onCreate()吗?我认为这不是一个好的解决方案...

P.S。我知道有关ViewPager和ViewPager2来管理TabLayout的选项卡。 ViewPager已弃用。使用ViewPager2时,我有一个奇怪的错误:第一个选项卡(索引为0)工作正常,但是在第二个选项卡中,我不能专注于任何输入(单击输入并立即失去焦点,不知道为什么)。

android android-fragments android-lifecycle
1个回答
0
投票

使用全局变量作为片段,首先创建片段,然后在需要时替换它们,例如:

private Fragment signInFragment = new SignInFragment();
private Fragment signUpFragment = new SignUpFragment();
int tabIndex = savedInstanceState == null ? 0 : 
savedInstanceState.getInt("tabIndex");
    Fragment f;
    switch (tabIndex) {
        case 0:
            f = signInFragment
            break;
        case 1:
            f = signUpFragment
            break;
        default:
            throw new UnsupportedOperationException();
    }
© www.soinside.com 2019 - 2024. All rights reserved.