【问题标题】:How to save instance state of fragment after using replace()?使用replace()后如何保存片段的实例状态?
【发布时间】:2019-04-10 10:28:34
【问题描述】:

我的活动有 3 个子片段 - 一次只显示 1 个。我正在使用 BottomNavigationView 在子片段之间切换。显示的初始子片段 GameFragment() 在通过 supportFragmentManager.beginTransaction().replace() 创建活动时膨胀,它替换了我的 XML 中的片段容器。

首先,让我向您展示我进入我的活动的完整生命周期,在replace() 上切换片段,然后在replace() 上切换回初始片段。这些日志语句仅与 Activity 和 Fragment A 相关(未显示 Fragment B 和 C)。

onCreate (Activity)
onAttach (Fragment A)
onCreate (Fragment A)
onCreateView (Fragment A)
onActivityCreated (Fragment A)

.replace() 片段 A 和片段 B

onPause (Fragment A)
onStop (Fragment A)

.replace() 片段 B 和片段 A

onAttach (Fragment A)
onCreate (Fragment A)
onCreateView (Fragment A)
onActivityCreated (Fragment A)

为了在使用replace()切换片段时保持我的片段状态,我尝试了以下方法,但都失败了。

  1. onDestroyView()的fragment中改变一个成员变量的值,然后在onActivityCreated()中访问它

  2. onDestroyView() 中添加到getArguments() 并在onActivityCreated() 中访问。

    class GameFragment : Fragment(), View.OnClickListener {
    
        var truthisvisible = "string"
    
        override fun onDestroyView() {
            super.onDestroyView()
            truthisvisible = "stringafter"
            arguments?.putString("success", "success")
    
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            return inflater.inflate(R.layout.fragment_game, container, false)
        }
    
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            Log.d("truthisvisible", truthisvisible) // prints "string"
            if (savedInstanceState != null){
                Log.d("LifecycleChange", "onActivityCreated savedInstanceState") // savedInstanceState is always null
            }
            super.onActivityCreated(savedInstanceState)
            Log.d("truthisvisible", truthisvisible) // prints "string"
            val print = arguments?.getString("success", "failure")
            Log.d("bool", "..." + print) // prints "...null"
    

我还尝试在onPause() 中更改变量truthisvisible,并尝试在onCreateView() 中接收变量,但是该变量永远不会更改为stringaftergetArguments() 也是如此 - 参数不会改变。

此外,所有这些方法中的savedInstanceState 都是null。虽然我希望这是因为 onSaveInstanceState() 在替换片段时永远不会被触发。

我在这里完全处于死胡同。调用replace() 时,如何更改或保存片段中的变量?如果您好奇,这是我的家长活动:

var initialFragmentLoad = false

class TruthOrDare : FragmentActivity(), BottomNavigationView.OnNavigationItemSelectedListener {

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        if (!initialFragmentLoad){
            return true
        }
        val selectedFragment = when (item.itemId){
            R.id.action_leaderboards -> LeaderboardsFragment()
            R.id.action_options -> OptionsFragment()
            else -> GameFragment()
        }
        Log.d("ChosenFragment", selectedFragment.toString())
        val transaction = supportFragmentManager.beginTransaction().replace(R.id.fragment_layout, selectedFragment)
        transaction.addToBackStack(null)
        transaction.commit()
        return true
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_truth_or_dare)
        bottomNav_truthordare.setOnNavigationItemSelectedListener(this)
        bottomNav_truthordare.selectedItemId = R.id.action_game
        initialFragmentLoad = true
        if (savedInstanceState != null) {
            return
        }
        val firstFragment = GameFragment()
        firstFragment.arguments = intent.extras
        supportFragmentManager.beginTransaction().replace(R.id.fragment_layout, firstFragment).commit();
    }

}

我也想知道为什么我无法使用上述方法更改变量。

【问题讨论】:

    标签: android android-fragments kotlin


    【解决方案1】:

    您可以使用处理程序类

    public static class GameHandler {
      public static string truthisvisible;
    }
    

    然后打电话

    Gamehandler.truthisvisible = "stringafter";
    val previousValue = Gamehandler.truthisvisible;
    

    【讨论】:

      【解决方案2】:

      您可以尝试阻止您的片段像这样在onCreateView() 中重新膨胀它的视图

       if (view != null) {
          ViewGroup parent = (ViewGroup) view.getParent();
          parent.removeView(view);
       } else {
          //here you put your current code from `onCreateView()`
       }
      

      【讨论】:

      • view 在这里指的是getView() 吗?我现在在我的代码中添加了我的 onCreateView - 我不确定你的代码如何适合我的函数:i.imgur.com/C1EJKja.png
      • 在你的代码中View view = inflater.inflate()...,然后是return view;
      猜你喜欢
      • 1970-01-01
      • 2014-01-11
      • 1970-01-01
      • 2010-09-14
      • 2013-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多