当前位置: 首页 > 知识库问答 >
问题:

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

马坚
2023-03-14

我正在进行一项活动,其中有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、 我知道ViewPager和ViewPager2用于管理TabLayout的选项卡。ViewPager已弃用。对于ViewPager2,我有一个奇怪的错误:第一个选项卡(索引为0)可以正常工作,但在第二个选项卡中,我无法专注于任何输入(单击输入并专注于固有的丢失,不知道为什么)。

共有1个答案

印季
2023-03-14

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

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();
    }
 类似资料:
  • 为了更新一些图像,我使用了“docker-compose pull”。然后我构建:'docker-compose build'。 下次我怎么避免这个?

  • 我使用for循环将学生详细信息添加到ArrayList。当我给第二个学生提供详细信息时,它会覆盖第一个数据。螺柱类 将数据添加到ArrayList的主类。 输出:第二个数据[2,2]后的实际输出辊数[1]。预期输出应为卷号: A1姓名: F1 L1性别:男性年龄: 11体育赛事:标枪 报名号:A2姓名:F2 L2性别:女年龄:14体育项目:100米跑 报名号:A3姓名:F3 L3性别:男性年龄:1

  • 我是实体框架的新手,所以如果这看起来很傻,请原谅我。 请考虑以下 json 对象: 让我们假设我们将其作为请求正文发送,以便在数据库中更新它。它是具有子实体的用户,如下所示: 现在,问题来了。虽然我希望用户能够创建一个新帐户(或联系人)或更新现有帐户(就像现在发生的那样),但我不希望规范发生同样的事情。用户只能添加或删除规范,无权创建新规范或更改规范的属性。 配置这种行为的正确方法是什么? 以下代

  • 我尝试在片段子类中使用onSaveInstanceState(Bundle outState)方法保存数据。 解释:我创建了一个类FragmentA,它扩展了这个类中的Fragment。我有一个变量名count,当我单击按钮时,count的值发生了变化(最初count=0)。我想保存count的值,即使方向发生了变化(纵向到横向,反之亦然)。我的MainActivity类动态加载片段。 我的代码:

  • 问题内容: 我正在尝试通过从客户端向服务器发送密钥和随机数来认证用户。 我的代码未向我显示客户端的响应。执行下面的代码时,我得到了一个空指针异常。 问题答案: 解决大多数问题的固定步骤: 阅读堆栈跟踪以确定哪一行代码引发NPE 在该行代码处设置一个断点 使用调试器,在遇到断点时,确定该行中的对象引用是 弄清楚为什么引用该文件(到目前为止,这是唯一实际的困难部分) 解决根本原因(也可能很困难)

  • 问题内容: 我有两个简单的Java代码。第一个将恒定功率定义为power = a.pow(b); 第二个将恒定功率定义为power = BigInteger.ONE.shiftLeft(b) 在命令行中设置内存标志- Xmx1024m,第一个代码可以正常工作,但是第二个代码却出现错误:java.lang.OutOfMemoryError:Java堆空间 我的问题:我应该在第二个代码中更改什么以避免