【问题标题】:How to handle a destruction of view when replacing fragment using FragmentManager?使用 FragmentManager 替换片段时如何处理视图破坏?
【发布时间】:2019-12-21 09:38:01
【问题描述】:

假设,我有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再次显示时,如何避免这种繁重的操作(如网络请求)?当FragmentA 应该再次显示时,我尝试使用popBackStack,但其结果是相同的。在这种情况下,Android 的设计似乎很不方便。你如何处理这样的问题?请不要推荐使用hide/show 方法。

【问题讨论】:

    标签: android fragment fragmentmanager


    【解决方案1】:

    当您的片段交互从片段 A 开始通过 Activity 到片段 B 时。它必须是您在后台堆栈中存在的第一个片段。每当您的 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() 
            }
        }```
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-24
      • 1970-01-01
      • 2013-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      • 1970-01-01
      相关资源
      最近更新 更多