在静态(3页)ViewPager2设置(其中ViewPager2位于片段中)中,我在FragmentStateAdapter后代中创建了3个片段。我什至将碎片收集在该子孙的表(MutableList<Fragment> = Vector<Fragment>())中,以供以后参考。 offscreenPageLimit设置为3,因此片段不会死亡,而只会继续和暂停。

一个片段是 map ,一个片段是具有几个实时数据引用(基于房间)的表设置,第三个片段是图片页面。

当离开这个ViewPager2片段并回收房间数据库(刷新内容)时,我的应用程序崩溃了……我发现,在FragmentStateAdapter后代中创建的三个片段没有被销毁(当然?)(空数据库无法由片段处理),因为FragmentStateAdapter不会杀死这些片段。当然,我可以在FragmentStateAdapter后代中杀死它们,但是没有任何简单的方法来处理这些死亡吗?

下面的许多代码都是基于模板的,因此有些不必要

代码提取:

AddStationFragment:

class AddStationFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
private var listener: OnFragmentInteractionListener? = null

private val TAG by lazy { this::class.java.simpleName }

private lateinit var adRequest: AdRequest

private lateinit var binding: FragmentAddStationBinding

private lateinit var viewModel: AddStationViewModel

var fragments: MutableList<Fragment> = Vector<Fragment>()

lateinit var addStationFragmentStateAdapter: AddStationFragmentStateAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    Log.i(TAG,"fra: onCreate()")
    super.onCreate(savedInstanceState)
    arguments?.let {
        param1 = it.getString(ARG_PARAM1)
        param2 = it.getString(ARG_PARAM2)
    }
}

override fun onResume() {
    Log.i(TAG,"fra: onResume()")
    super.onResume()

    activity?.let {activity->
        activity.fab?.let { fab ->
            fab.hide()
            fab.setImageDrawable(resources.getDrawable(R.drawable.ic_baseline_check_24, context?.theme))
            fab.clearAnimation()
            //fab.isEnabled = false

            fab.setOnClickListener { view ->
                Log.i(TAG,"fab.clicked !")
            }

            //fab.show()
        }

        (activity as MainActivity).setOptionsMenu(OptionsMenuSet.ADDSTATION)
        activity.bottom_navigation.visibility=View.GONE

        listener?.registerFragment(this)
    }

}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

    Log.i(TAG,"fra: onViewCreated")

    val tabtext = arrayOf(
        "Location",
        "Address",
        "Enterprise")

    val iconresource = arrayOf(
        R.drawable.ic_add_location_black_24dp,
        R.drawable.ic_info_outline_black_24dp,
        R.drawable.ic_baseline_business_24)

    TabLayoutMediator(
        binding.addStationTabLayout,
        binding.addStationViewPager2,
        TabLayoutMediator.TabConfigurationStrategy { tab: TabLayout.Tab, position: Int ->
            tab.text = tabtext[position]
            tab.setIcon(iconresource[position])
            tab.icon?.let { icon ->
                DrawableCompat.setTint(
                    icon,
                    ContextCompat.getColor(activity as Context, R.color.cardBG_lightred))
            }
            /*tab.icon?.setColorFilter(
                ContextCompat.getColor(activity as Context, R.color.cardBG_lightred),
                PorterDuff.Mode.SRC_IN)*/ //Deprecated


        }
    ).attach()



    //super.onViewCreated(view, savedInstanceState)
}

override fun onDestroy() {
    Log.i(TAG,"fra: onDestroy()")

    Log.i(TAG,"fra: Childfragment size: ${childFragmentManager.fragments.size}")



    super.onDestroy()
}


override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // Inflate the layout for this fragment
    Log.i(TAG,"fra: onCreateView()")

    binding = FragmentAddStationBinding.inflate(inflater, container, false)

    context?:return binding.root

    adRequest = AdRequest.Builder().build()

    binding.addStationAdView.loadAd(adRequest)

    addStationFragmentStateAdapter = AddStationFragmentStateAdapter(
        activity?:return binding.root,fragments)

    binding.addStationViewPager2.offscreenPageLimit = 3
    binding.addStationViewPager2.adapter = addStationFragmentStateAdapter

    val factory = InjectorUtils.provideAddStationViewModelFactory(context?:return binding.root)
    viewModel = ViewModelProvider(this, factory).get(AddStationViewModel::class.java)

    viewModel.liveNewStationForUser.observe(viewLifecycleOwner, Observer { station ->
        Log.i(TAG,"onCreateView liveNewStationForUser station = $station")
    })

    AddStationRepository.createTemplate("")

    return binding.root
}

// TODO: Rename method, update argument and hook method into UI event
fun onButtonPressed(uri: Uri) {
    listener?.onFragmentInteraction(uri)
}

override fun onAttach(context: Context) {
    Log.i(TAG,"fra: onAttach()")
    super.onAttach(context)
    if (context is OnFragmentInteractionListener) {
        listener = context
    } else {
        throw RuntimeException(context.toString() + " must implement OnFragmentInteractionListener")
    }
}

override fun onPause() {
    Log.i(TAG,"fra: onPause()")
    super.onPause()
}

override fun onDetach() {
    Log.i(TAG,"fra: onDetach()")
    super.onDetach()
    listener = null
}

/**
 * This interface must be implemented by activities that contain this
 * fragment to allow an interaction in this fragment to be communicated
 * to the activity and potentially other fragments contained in that
 * activity.
 *
 *
 * See the Android Training lesson [Communicating with Other Fragments]
 * (http://developer.android.com/training/basics/fragments/communicating.html)
 * for more information.
 */
interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    fun onFragmentInteraction(uri: Uri)
    fun registerFragment(fragment: Fragment)
    fun unregisterFragment(fragment: Fragment)
}

companion object {
    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment AddStationFragment.
     */
    // TODO: Rename and change types and number of parameters
    @JvmStatic
    fun newInstance(param1: String, param2: String) =
        AddStationFragment().apply {
            arguments = Bundle().apply {
                putString(ARG_PARAM1, param1)
                putString(ARG_PARAM2, param2)
            }
        }
}
}

AddStationFragmentStateAdapter:(FragmentStateAdapter的后代)
class AddStationFragmentStateAdapter(
fragmentActivity: FragmentActivity,
private val fragmentList: MutableList<Fragment>
) :
FragmentStateAdapter(fragmentActivity) {

private val TAG by lazy {this::class.java.simpleName}

override fun createFragment(position: Int): Fragment {

    Log.i(TAG, "createFragment position = $position")

    val fragment: Fragment = when (position) {
        0 -> FragmentAddStationMap()
        1 -> FragmentAddStationInfo()
        else -> FragmentAddStationEnterprise()
    }

    if (fragmentList.size <= position)
        fragmentList.add(fragment)
    else
        fragmentList[position] = fragment

    Log.i(TAG, "fra: fragmentList.size = ${fragmentList.size}")

    return fragment
}



override fun getItemCount(): Int {
    Log.i(TAG,"fra: fragmentListSize = ${fragmentList.size}")
    return 3
}

}

所以...您的建议是,我应该在onDestroy()中为AddStationFragment做些什么,我已经检查了childFragmentManager,但是那里没有任何片段(如我所期望的,因为我在fragmentActivity调用中提供了FragmentStateAdapter(在(子代FragmentStateAdapter)(子代AddStationFragmentStateAdapter),它们在哪里坐着以及(I)应该以最佳方式摧毁谁?

RG

最佳答案

实际上,我不是直接为我的问题找到答案,而是找到了一种可能对其他人也有相同问题的解决方法。

A.在FragmentStateAdapter降序(即AddStationFragmentStateAdapter)中,将“人工” fragmentList更改为public,这样您就可以从外部访问它。

B.然后在onDestroy()片段(即ViewPager2)的AddStationFragment方法中,循环访问公共(public)fragmentList并调用fragment.parentFragmentManager.beginTransaction().remove(fragment).commit()
“B”将从它所在的列表中释放该片段,并且一切都整齐干净。

代码更改:

在AddStationFragmentStateAdapter中,我们将fragmentList设置为public:

class AddStationFragmentStateAdapter(
 fragmentActivity: FragmentActivity,
 public var fragmentList: MutableList<Fragment>  //changed to public
) :
FragmentStateAdapter(fragmentActivity) {

private val TAG by lazy {this::class.java.simpleName}
...

并在AddStationFragment onDestroy()中:
override fun onDestroy() {
    Log.i(TAG,"fra: onDestroy()")

    Log.i(TAG,"fra: Childfragment size: ${childFragmentManager.fragments.size}")

    Log.i(TAG,"fra: addStationFragmentStateAdapter.fragmentList.size = ${addStationFragmentStateAdapter.fragmentList.size}")

    addStationFragmentStateAdapter.fragmentList.forEach { fragment:Fragment ->
        fragment.parentFragmentManager.beginTransaction().remove(fragment).commit()
    }

    super.onDestroy()
}

RG

07-27 20:35