片段的内容在我导航回去时消失了

问题描述 投票:3回答:2

我在单活动应用程序中使用导航组件进行导航,但我有一个片段的奇怪行为。这只是解释使用图像。

我有一个ViewPager片段。 ViewPager包含另外两个片段,所以看起来如下:

enter image description here

鸟 - 第一个片段,测试 - 第二个。底部元素是底部导航,它不是片段的一部分。片段位于工具栏和底部导航之间。

这个包含ViewPager的片段不是起始片段,它位于堆栈中间的某个位置。

因此,当用户点击底部菜单项时,此导航代码正在运行(来自Main Activity):

 bottom_navigation.apply {
            itemIconTintList = null
            setOnNavigationItemSelectedListener { item ->
                when (item.itemId) {
                    R.id.about_bottom -> {
                        findNavController(R.id.host).navigate(R.id.toAboutUs)
                    }
                    R.id.error_bottom -> {
                        findNavController(R.id.host).navigate(R.id.toMessage)
                    }
                }
                true
            }
        }

其中toMessage / toAboutUs是另一个片段的全球点。

那有什么问题。当用户点击底部菜单项时,一切正常。但当他“退回”时,片段中的内容消失了。它只是看到:

enter image description here

我甚至无法提出原因。我知道ViewPager上的“主要”片段和片段没有重新创建,为什么它们会丢失内容?

我没有在任何地方覆盖后退按钮的行为。我只是使用主机片段的app:defaultNavHost="true"


如何传输数据:当用户单击按钮以使用ViewPager打开Fragment时,数据从DB加载并保存到ViewModel,然后用户才会传输到此Fragment。创建两个子片段时,它们从ViewModel加载数据。我无法清除ViewModel的代码,因此当用户按下它时,我的ViewModel包含100%的内容。但它没有显示出来。

UPD:花一些时间,我意识到当我向后导航时,两个“子”片段没有重新创建,但主片段重新创建。我认为问题是关于它的,但仍然不明白到底在哪里。

我需要你的帮助来了解发生了什么。


Upd:提供一些Fragments创建代码。 BaseCompatFragment扩展了Fragment

MainFragment(另外两个片段的容器):

class QuestionFragment : BaseCompatFragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_question, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        pager.adapter = QuestionViewPagerAdapter(fragmentManager!!)
        activity?.toolbar_title?.text = getString(R.string.title_question,1)

        layout_tab.apply {
            setupWithViewPager(pager)
            tabIconTint = null
            getTabAt(0)?.setIcon(R.drawable.ic_type_bird)
            getTabAt(1)?.setIcon(R.drawable.ic_hints)
        }
    }
}

问题ViewPagerAdapter

    class QuestionViewPagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {

        override fun getItem(position: Int): BaseCompatFragment {
            when (position) {
                0 -> return HintsFragment()
                1 -> return BaseInfoFragment()
            }
            return HintsFragment()
        }

        override fun getCount(): Int {
            return 2
        }
    }

HintsFragment(鸟)

class HintsFragment : BaseCompatFragment(), HintsFragmentContract.View {

    @Inject
    lateinit var presenter: HintsFragmentPresenter

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_hints, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        LibApp.get().injector.inject(this)
        presenter.attach(this)

        val animalWithHints =
            ViewModelProviders.of(activity!!).get(AnimalViewModel::class.java).getData().value

        val adapter = HintsAdapter(callback = { id ->
            //Some code will be here soon
        })
        //Do smth with content
        adapter.hintsList = animalWithHints?.animal?.hints?.split("///") as ArrayList<String>
        adapter.hintsStorage = animalWithHints.hints?.get(0) ?: Hints()

        recycler_hints.layoutManager = verticalManager(context)
        recycler_hints.adapter = adapter
    }
}

盆地碎片(测试)

class BaseInfoFragment : BaseCompatFragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_base_info, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val animalWithHints =
            ViewModelProviders.of(activity!!).get(AnimalViewModel::class.java).getData().value

        //A lot of logic to hide/show content, don't think it can be intresting

        val isBaseInfoOpen = animalWithHints?.hints?.get(0)?.baseInfoOpened == 1
        setBlockLayoutState(!isBaseInfoOpen)

        if (isBaseInfoOpen) {
            openContent(animalWithHints)
        } else {
            text_base_info.text = getString(R.string.base_info_price, 100)
            btn_base_info_positive.setOnClickListener {
                if (btn_base_info_negative.visibility == View.GONE) {
                    btn_base_info_negative.visibility = View.VISIBLE
                    text_base_info.text = getString(R.string.default_doubts)
                } else {
                    openContent(animalWithHints)
                }
            }

            btn_base_info_negative.setOnClickListener {
                it.visibility = View.GONE
                text_base_info.text = getString(R.string.base_info_price, 100)
            }
        }
    }

    private fun getRareIcon(rare: Int, context: Context): Drawable {
        return when (rare) {
            1 -> ContextCompat.getDrawable(context, R.drawable.ic_rare_fine)!!
            2 -> ContextCompat.getDrawable(context, R.drawable.ic_rare_medium)!!
            3 -> ContextCompat.getDrawable(context, R.drawable.ic_rare_bad)!!
            else -> ContextCompat.getDrawable(context, R.drawable.ic_warning)!!
        }
    }

    private fun getRareText(rare: Int): String {
        return when (rare) {
            1 -> getString(R.string.base_info_rare_1)
            2 -> getString(R.string.base_info_rare_2)
            3 -> getString(R.string.base_info_rare_3)
            else -> getString(R.string.base_info_rare_4)
        }
    }

    private fun setBlockLayoutState(state: Boolean) {
        base_info_closer.visibility = when {
            state -> View.VISIBLE
            else -> View.GONE
        }
        base_info_content.visibility = when {
            state -> View.GONE
            else -> View.VISIBLE
        }
    }

    private fun openContent(animalWithHints: AnimalWithHints?) {
        (img_closed_base_info.drawable as Animatable).start()
        rare_img.setImageDrawable(getRareIcon(animalWithHints?.animal?.rare ?: 0, activity!!))
        rare_text.text = getRareText(animalWithHints?.animal?.rare ?: 0)
        setBlockLayoutState(false)
    }
}
android android-fragments kotlin navigation android-viewpager
2个回答
2
投票

我想,问题在这里:QuestionViewPagerAdapter(fragmentManager!!)当你直接在你的活动上添加片段时,你需要使用getFragmentManager() / getSupportFragmentManager()。但是当你需要在另一个片段上添加片段时,你需要使用getChildFragmentManager()

来自getSupportFragmentManager() documentation

返回FragmentManager以与与此活动关联的片段进行交互。

因此,这就是为什么你的鸟和测试片段在它们的父片段没有重建的原因。

来自getChildFragmentManager() doc

返回一个私有FragmentManager,用于放置和管理此Fragment中的Fragment。

这应该可以解决问题。希望能帮助到你。


0
投票

在MainFragment的onCreateView上,尝试将if(!isAdded())返回;某处。我之前遇到过同样的问题,你的代码与我的有点不同。我做的是把if(!isAdded())返回;

© www.soinside.com 2019 - 2024. All rights reserved.