UI 重复设置 - 数据绑定、MVVM、导航组件
UI getting set repeatedly - Data binding, MVVM, Navigation Components
我在当前项目中使用数据绑定和 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
更新:我将计划获取逻辑移到了 onResume,它处理了 UI 的闪烁。但是当用户返回屏幕时,适配器会再次设置。这与片段生命周期有关,所以我认为没有办法解决这个问题。如果我错了,请纠正我。
override fun onResume() {
super.onResume()
savingPlanViewModel.getAllSavingPlan()
}
附加说明:我正在使用 android 导航组件。
片段本身是其 xml 中包含 viewpager 的父片段的一部分。 viewpager 是活动/非活动计划子片段的主机。父 class 查看寻呼机将屏幕外页面限制设置为 2。
savingPlanViewPager.adapter = SavingPlanViewPagerAdapter(childFragmentManager)
savingPlanViewPager.offscreenPageLimit = 2
savingPlanTabLayout.setupWithViewPager(savingPlanViewPager)
我最终使用惰性初始化只设置了一次适配器。这是解决方案,以防有人正在寻找它:
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必然会反复触发,但是我们可以像上面的代码一样通过lazy来控制adapter和数据的初始化。
我在当前项目中使用数据绑定和 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
更新:我将计划获取逻辑移到了 onResume,它处理了 UI 的闪烁。但是当用户返回屏幕时,适配器会再次设置。这与片段生命周期有关,所以我认为没有办法解决这个问题。如果我错了,请纠正我。
override fun onResume() {
super.onResume()
savingPlanViewModel.getAllSavingPlan()
}
附加说明:我正在使用 android 导航组件。
片段本身是其 xml 中包含 viewpager 的父片段的一部分。 viewpager 是活动/非活动计划子片段的主机。父 class 查看寻呼机将屏幕外页面限制设置为 2。
savingPlanViewPager.adapter = SavingPlanViewPagerAdapter(childFragmentManager)
savingPlanViewPager.offscreenPageLimit = 2
savingPlanTabLayout.setupWithViewPager(savingPlanViewPager)
我最终使用惰性初始化只设置了一次适配器。这是解决方案,以防有人正在寻找它:
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必然会反复触发,但是我们可以像上面的代码一样通过lazy来控制adapter和数据的初始化。