使用FragmentManager替换片段时如何处理视图破坏?

时间:2019-12-21 09:38:01

标签: android fragment fragmentmanager

假设我有SomeActivity。它使用以下代码立即显示FragmentA

supportFragmentManager.beginTransaction()
        .replace(R.id.fragmentView, FragmentA(), "fragment-a-tag")
        .addToBackStack(null)
        .commit()

当然,在那之后创建FragmentA。它发出一些网络请求并显示数据。假设FragmentA中发生了一些事情(例如,单击按钮),并且通知了该SomeActivitySomeActivity应该显示FragmentB而不是FragmentA。这是我的方法:

supportFragmentManager.beginTransaction()
                .replace(R.id.fragmentView, FragmentB(), "fragment-b-tag")
                .addToBackStack(null)
                .commit()

FragmentB在其工具栏上具有后退按钮。单击后,应再次显示FragmentA。当然,FragmentB会向SomeActivity通知后退按钮按下,SomeActivity会通过以下方式显示FragmentA

supportFragmentManager.findFragmentByTag("product")
                ?.let {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.fragmentView, it, "fragment-a-tag")
                        .addToBackStack(null)
                        .commit()
                }

它通过后退堆栈按其标签搜索FragmentA,如果存在,则仅显示它。但是问题是FragmentA的视图被破坏了。这意味着,将再次执行Fragment的整个生命周期。正如我已经提到的,在生命周期的某个时刻,FragmentA中存在一个网络请求。这意味着它将再次执行,这是我要避免的事情。即使FragmentA的视图由于replace函数而被破坏,其实例也存在于后堆栈中。这意味着它的数据(一些变量)也存在并且仍然存在。因此,问题是当再次显示FragmentA时如何避免繁重的操作(例如网络请求)?当popBackStack应该再次显示时,我尝试使用FragmentA,但结果相同。在这种情况下,Android的设计似乎很不方便。您如何处理此类问题?请不要使用hide/show方法。

1 个答案:

答案 0 :(得分:0)

当您的片段交互通过活动从片段A开始到片段B时。它必须是您的第一个片段存在于Backstack中。每当您的onviewcreated调用尝试限制您的片段以重新创建或膨胀您片段的xml。为此,您必须手动检查视图是否已经存在,并且不要在onCreateView中对其进行膨胀。

private var isReload: Boolean= false
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

  if(initView!=null)
        {
            isReload=true
        }
        else {
            introbinding = DataBindingUtil.inflate(inflater, R.layout.fragment_intro_one, container, false)
            initView = introbinding.getRoot()
        }
        return initView
}


Do in onViewCreated

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        if(!isReload) {
            initViews()   // get View ids
            initMembers() // get values or network calls
            setListeners() 
        }
    }```