【问题标题】:UI getting set repeatedly - Data binding, MVVM, Navigation ComponentsUI 重复设置 - 数据绑定、MVVM、导航组件
【发布时间】:2023-04-09 02:08:01
【问题描述】:

我在当前项目中使用数据绑定和 MVVM。这是我正在处理的屏幕之一的代码:

class ActivePlansFragment : Fragment() {

    private lateinit var savingPlanViewModel: SavingPlanViewModel
    private var isFinancialFreedomPlanOpted = false

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        printLog("On Create View")
        return inflater.inflate(R.layout.fragment_active_plans, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        savingPlanViewModel = activityViewModels {
            printLog("Setting Adapter For Active plans")
            rvAllPlans.apply {
                adapter = ActivePlansAdapter().apply {
                    mBaseAdapterClickListener = { view, position, item ->
                        if( view.id == R.id.tvAction ) {
                            if( isCurrentDestination(R.id.savingPlanListFragment) ) {
                                selectedNeoSavingPlan = item
                                findNavController().navigate(SavingPlanListFragmentDirections.actionSavingPlanListFragmentToAddFundsFragment())
                            }
                        } else {
                            if( isCurrentDestination(R.id.savingPlanListFragment) ) {
                                selectedNeoSavingPlan = item
                                findNavController().navigate(SavingPlanListFragmentDirections.actionSavingPlanListFragmentToSavingPlanDetailsFragment())
                            }
                        }
                    }
                    onEmptyOrNot = { isEmpty ->
                        emptyPlansLayout.changeVisibility(isEmpty)
                    }
                    //Update : getAllSavingPlan()
                    observe(allSavingPlanResponsesMutableLiveData) {
                        it?.onChanged { inProgress, failure, list ->
                            //fabCreatePlan.isEnabled = !inProgress
                            planRefreshLayout.isRefreshing = inProgress
                            if (!inProgress)
                                if (failure != null) {
                                    handleFailures(failure) { getAllSavingPlan() }
                                    allSavingPlanResponsesMutableLiveData.clearValue()
                                } else if (list != null) {
                                    removeAll()
                                    val filteredList = list.filter { plan ->
                                        plan.active
                                                || plan.status == NeoSavingPlanResponse.COMPLETED
                                                || plan.status == NeoSavingPlanResponse.CREATE_INITIATED
                                                || plan.status == NeoSavingPlanResponse.DELETE_INITIATED
                                    }
                                    addAll(filteredList)
                                    isFinancialFreedomPlanOpted = list.find { plan -> plan.planType == NeoMasterSavingPlan.FINANCIAL_FREEDOM_PLAN } != null
                                }
                        }
                    }
                }
            }
            planRefreshLayout.setOnRefreshListener {
                getAllSavingPlan()
            }
        }

    }
}

我面临的问题是适配器,当我导航回屏幕时,其余逻辑将重新设置。我正在寻求有关在何处设置 UI 逻辑以避免重置 UI 的帮助。

> Logcat logs :    
>
> D/ActivePlansFragment: On Create View 
> D/ActivePlansFragment: Setting Adapter For Active plans 
> D/ActivePlansFragment: On Create View 
> D/ActivePlansFragment: Setting Adapter For Active plans

更新:我将计划获取逻辑移至处理 UI 闪烁的 onResume。但是当用户返回屏幕时,适配器会再次设置。这与片段生命周期有关,所以我认为没有办法解决这个问题。如果我错了,请纠正我。

override fun onResume() {
        super.onResume()
        savingPlanViewModel.getAllSavingPlan()
 }

附加说明:我使用的是安卓导航组件。

片段本身是其 xml 中带有 viewpager 的父片段的一部分。 viewpager 是活动/非活动计划子片段的主机。父类视图分页器的屏幕外页面限制设置为 2。

savingPlanViewPager.adapter = SavingPlanViewPagerAdapter(childFragmentManager)
savingPlanViewPager.offscreenPageLimit = 2
savingPlanTabLayout.setupWithViewPager(savingPlanViewPager)

【问题讨论】:

  • 您的意思是“导航返回”时再次调用“创建视图”? “导航回来”是什么意思?您在顶部有一些活动并按下回或者您在处理一些片段交易?
  • 分片到分片导航,我用的是导航组件。
  • 不幸的是我不知道导航组件是如何工作的,但上面的代码不是你的问题。如果调用了onCreateView,则意味着每次都重新创建Fragment。所以看看负责片段的代码。你在导航组件上做错了
  • 上述代码中的片段是在视图分页器中托管 2 个单独片段的父片段的一部分。屏幕外页面限制已设置为 2。它有任何提示吗? @YavorMitev

标签: android mvvm android-databinding android-livedata android-architecture-navigation


【解决方案1】:

我最终只使用了一次延迟初始化来设置适配器。如果有人正在寻找它,这是解决方案:

class ActivePlansFragment : Fragment() {

    private lateinit var savingPlanViewModel: SavingPlanViewModel
    private var isFinancialFreedomPlanOpted = false
    private val navController : NavController by lazy { findNavController() }

    private val adapterClickListener : ((view : View, position : Int, item : NeoSavingPlanResponse) -> Unit) = { view, _, item ->
        if( view.id == R.id.tvAction ) {
            if( isCurrentDestination(R.id.savingPlanListFragment) ) {
                savingPlanViewModel.selectedNeoSavingPlan = item
                navController.navigate(SavingPlanListFragmentDirections.actionSavingPlanListFragmentToAddFundsFragment())
            }
        } else {
            if( isCurrentDestination(R.id.savingPlanListFragment) ) {
                savingPlanViewModel.selectedNeoSavingPlan = item
                navController.navigate(SavingPlanListFragmentDirections.actionSavingPlanListFragmentToSavingPlanDetailsFragment())
            }
        }
    }

    private val onEmptyAdapterListener : ((isEmpty: Boolean) -> Unit) = {
            isEmpty -> emptyPlansLayout.changeVisibility(isEmpty)
    }

    private val activePlansAdapter: ActivePlansAdapter by lazy {
        ActivePlansAdapter().apply {
            mBaseAdapterClickListener = adapterClickListener
            onEmptyOrNot = onEmptyAdapterListener
        }
    }

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        savingPlanViewModel = activityViewModels {
            getAllSavingPlan()
        }
        rvAllPlans.apply { adapter = activePlansAdapter }
        planRefreshLayout.setOnRefreshListener { savingPlanViewModel.getAllSavingPlan() }
        setupObserver()
    }

    private fun setupObserver() {
        savingPlanViewModel.apply {
            observe(allSavingPlanResponsesMutableLiveData) {
                it?.onChanged { inProgress, failure, list ->
                    planRefreshLayout.isRefreshing = inProgress
                    if (!inProgress)
                        if (failure != null) {
                            handleFailures(failure) { savingPlanViewModel.getAllSavingPlan() }
                            allSavingPlanResponsesMutableLiveData.clearValue()
                        } else if (list != null) {
                            activePlansAdapter.removeAll()
                            val filteredList = list.filter { plan ->
                                plan.active
                                        || plan.status == NeoSavingPlanResponse.COMPLETED
                                        || plan.status == NeoSavingPlanResponse.CREATE_INITIATED
                                        || plan.status == NeoSavingPlanResponse.DELETE_INITIATED
                            }
                            activePlansAdapter.addAll(filteredList)
                            isFinancialFreedomPlanOpted = list.find {
                                    plan -> plan.planType == NeoMasterSavingPlan.FINANCIAL_FREEDOM_PLAN
                            } != null
                        }
                }
            }
        }
    }

}

onCreateView 必然会反复触发,但是我们可以通过惰性控制适配器和数据初始化,如上代码所示。

【讨论】:

    猜你喜欢
    • 2011-04-07
    • 2015-06-04
    • 2017-12-23
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 2013-01-07
    相关资源
    最近更新 更多