在静态(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