Android fragments 如何销毁使用fragmentstateadapter(viewpager2)创建的片段

Android fragments 如何销毁使用fragmentstateadapter(viewpager2)创建的片段,android-fragments,kotlin,android-room,android-livedata,android-viewpager2,Android Fragments,Kotlin,Android Room,Android Livedata,Android Viewpager2,在ViewPager2位于片段中的静态(3页)ViewPager2设置中,我在FragmentStateAdapter子体中创建了3个片段。我甚至在该子体的一个表(MutableList=Vector())中收集了片段,以供以后参考。offscreenPageLimit设置为3,因此片段不会消失,只会恢复并暂停 一个片段是地图,一个片段是带有多个livedata引用的表设置(基于房间),第三个片段是图片页 当离开这个ViewPager2片段并回收房间数据库(刷新内容)时,我的应用程序崩溃了。。。

在ViewPager2位于片段中的静态(3页)ViewPager2设置中,我在FragmentStateAdapter子体中创建了3个片段。我甚至在该子体的一个表(
MutableList=Vector()
)中收集了片段,以供以后参考。
offscreenPageLimit
设置为
3
,因此片段不会消失,只会恢复并暂停

一个片段是地图,一个片段是带有多个livedata引用的表设置(基于房间),第三个片段是图片页

当离开这个ViewPager2片段并回收房间数据库(刷新内容)时,我的应用程序崩溃了。。。我突然想到,在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)
            }
        }
}
}
class AddStationFragment:Fragment(){
//TODO:重命名和更改参数类型
私有变量param1:字符串?=null
私有变量param2:字符串?=null
私有变量侦听器:OnFragmentInteractionListener?=null
惰性{this::class.java.simpleName}的私有val标记
私有lateinit var adRequest:adRequest
私有lateinit变量绑定:FragmentAddStationBinding
私有lateinit变量viewModel:AddStationViewModel
变量片段:MutableList=Vector()
lateinit变量addStationFragmentStateAdapter:addStationFragmentStateAdapter
重写创建时的乐趣(savedInstanceState:Bundle?){
Log.i(标记“fra:onCreate()”)
super.onCreate(savedInstanceState)
争论?让我们{
param1=it.getString(ARG_param1)
param2=it.getString(ARG_param2)
}
}
重写onResume(){
Log.i(标记“fra:onResume()”)
super.onResume()
活动?.let{activity->
activity.fab?.let{fab->
制作隐藏
工厂setImageDrawable(resources.getDrawable(R.drawable.ic\u baseline\u check\u 24,context?.theme))
制作clearAnimation()
//fab.isEnabled=false
fab.setOnClickListener{view->
Log.i(标记“fab.clicked!”)
}
//制作秀
}
(活动作为主活动)。设置选项菜单(选项菜单Uset.ADDSTATION)
activity.bottom\u navigation.visibility=View.GONE
侦听器?.registerFragment(此)
}
}
覆盖已创建的视图(视图:视图,保存状态:捆绑?){
Log.i(标记“fra:onViewCreated”)
val tabtext=arrayOf(
“地点”,
“地址”,
“企业”)
val iconresource=arrayOf(
R.drawable.ic\U添加位置\U黑色\U 24dp,
R.drawable.ic_信息_轮廓_黑色_24dp,
R.drawable.ic_基线_业务_24)
调停人(
binding.addStationTableOut,
binding.addStationViewPager2,
TabLayoutMediator.TabConfigurationStrategy{tab:TabLayout.tab,位置:Int->
tab.text=tabtext[位置]
选项卡.设置图标(iconresource[位置])
tab.icon?.let{icon->
DrawableCompat.setTint(
偶像
ContextCompat.getColor(活动作为上下文,R.color.cardBG_浅红色))
}
/*选项卡.图标?.setColorFilter(
ContextCompat.getColor(活动作为上下文,R.color.cardBG_浅红色),
PorterDuff.Mode.SRC_IN)*///已弃用
}
)附(
//super.onViewCreated(视图,savedInstanceState)
}
重写onDestroy(){
Log.i(标记“fra:onDestroy()”)
Log.i(标记,“fra:childfragmentsize:${childFragmentManager.fragments.size}”)
super.ondestory()
}
覆盖创建视图(
充气器:布局充气器,容器:视图组?,
savedInstanceState:捆绑?
):查看{
//为该碎片膨胀布局
Log.i(标记“fra:onCreateView()”)
绑定=碎片添加站绑定。充气(充气机、容器、假)
上下文?:返回binding.root
adRequest=adRequest.Builder().build()
binding.addStationAdView.loadAd(adRequest)
addStationFragmentStateAdapter=addStationFragmentStateAdapter(
活动?:返回绑定。根,片段)
binding.addStationViewPager2.offscreenPageLimit=3
binding.addStationViewPager2.adapter=addStationFragmentStateAdapter
val factory=InjectorUtils.providedStationViewModelFactory(上下文?:返回binding.root)
viewModel=ViewModelProvider(this,factory).get(AddStationViewModel::class.java)
viewModel.liveNewStationForUser.observe(viewLifecycleOwner,Observer{station->
Log.i(标记“onCreateView liveNewStationForUser station=$station”)
})
AddStationRepository.createTemplate(“”)
返回binding.root
}
//TODO:重命名方法、更新参数并将方法挂接到UI事件中
按下按钮(uri:uri){
侦听器?.onFragmentInteraction(uri)
}
重写转速表(上下文:上下文){
Log.i(标记“fra:onAttach()”)
super.onAttach(上下文)
if(上下文是OnFragmentInteractionListener){
侦听器=上下文
}否则{
抛出运行时异常(context.toString()+“必须实现OnFragmentInteractionListener”)
}
}
覆盖暂停(){
Log.i(标记“fra:onPause()”)
super.onPause()
}
覆盖连接(){
Log.i(标记“fra:onDetach()”)
super.onDetach()
侦听器=null
}
/**
*此接口必须由包含以下内容的活动实现
*片段,以允许通信此片段中的交互
*该活动以及其中可能包含的其他片段
*活动。
*
*
*请参阅Android培训课程[与其他片段交流]
* (http://develo
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
}

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

private val TAG by lazy {this::class.java.simpleName}
...
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()
}
class MainPagerAdapter(fragment: MyParentFragment) : FragmentStateAdapter(fragment) {}