对话框关闭且父片段返回视图后,ViewModel 仍显示旧数据

ViewModel still displaying old data after dialog dismissed and parent fragment back to view

我仍在尝试使用 viewmodels,现在有点困惑,因为我还有一个对话框和 recyclerview 项目,但如果我能得到任何帮助,我会尽量清楚.

我有一个包含项目的对话框,当其中一个被选中并关闭时,应该 return 数据到我的调用片段,以便所选项目显示在该视图下。

但是,一旦选择了项目并关闭了对话框,我就不会看到 UI 上显示的新选定项目,而是旧项目。 (当片段第一次启动时,它会显示在我的列表中设置为选中的项目。选中的值最初是硬编码的,但在单击该项目时更新,当我在内部调试 viewmodel 观察器时,我可以看到更新已经发生对话框的 onDismiss 方法)。

我在这上面花了几个小时,并尝试了一些不同的事情,例如在 onResume 或 onDismiss 中调用视图模型,并根据 this post 更改要启动的视图模型 by by activityViewModels() 但是none 到目前为止,这些都有效,我想我现在被困住了。下面是我最新版本的代码。

class CovidCheckInFragment : Fragment(R.layout.fragment_covid_check_in) {

var navController: NavController? = null
private val model: MainViewModel by activityViewModels()

@RequiresApi(Build.VERSION_CODES.M)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    navController = Navigation.findNavController(view)
    
    model.userMutableLiveData.observe(viewLifecycleOwner, Observer<Any?> { list ->
        if (list != null)

            (list as Iterable<*>).map {

                if ((it as ModelDialogOption).selected == true) {
                    tvHeader.text = it.title
                }

            }

    })

}

}

..

class MyDialogFragment : DialogFragment(), RecyclerDialogOptionsItem.AdapterListener {

private val viewModel: MainViewModel by activityViewModels()
private lateinit var adapter: GroupAdapter<GroupieViewHolder>
var selectedPosition = -1

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setStyle(STYLE_NO_TITLE, R.style.AppTheme_Dialog_Custom)
}

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

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    
    rvOptions.layoutManager = LinearLayoutManager(activity)
    adapter = GroupAdapter()
    rvOptions.adapter = adapter


    ivClose.setOnClickListener {

        this.dismiss()
    }


    initViewModel()
}

private fun initViewModel() {

    viewModel.userMutableLiveData.observe(this, Observer { list ->
        for (i in list!!) {
            adapter.add(
                RecyclerDialogOptionsItem(
                    this@MyDialogFragment,
                    i,
                    this@MyDialogFragment
                )
            )
        }

    })

}

override fun onClickItem(position: Int) {

    selectedPosition = position
    adapter.notifyDataSetChanged()

    Log.i("clicked", "position: $position")
}

}

..

class MainViewModel : ViewModel() {

private var list: ArrayList<ModelDialogOption>? = null

val userMutableLiveData: MutableLiveData<ArrayList<ModelDialogOption>?> = MutableLiveData()

init {
    populateList()
    userMutableLiveData.value = list!!
}

private fun populateList() {

    list = ArrayList()

    list!!.add(ModelDialogOption("Prefer not to say", false))
    list!!.add(ModelDialogOption("16-39", false))
    list!!.add(ModelDialogOption("40-59", true))
    list!!.add(ModelDialogOption("60+", false))
}

}

..

class RecyclerDialogOptionsItem(
private val fragment: MyDialogFragment,
private val modelDialogOption: ModelDialogOption,
private val adapterListener: AdapterListener
) : Item<GroupieViewHolder>() {

companion object {
    var clickListener: AdapterListener? = null
}

override fun bind(viewHolder: GroupieViewHolder, position: Int) {

    viewHolder.apply {

        with(viewHolder.itemView) {

            tvTitle.text = modelDialogOption.title

            clickListener = adapterListener

            if (fragment.selectedPosition == position) {
                ivChecked.visible()
                modelDialogOption.selected = true

            } else {
                ivChecked.invisible()
                modelDialogOption.selected = false
            }

            itemView.setOnClickListener {

                clickListener?.onClickItem(adapterPosition)

            }

        }

    }

}

override fun getLayout() = R.layout.rv_options_item_row

interface AdapterListener {
    fun onClickItem(position: Int)
}

}

非常感谢。

你的主视图模型应该是这样的

class MainViewModel : ViewModel() {

private var list: ArrayList<ModelDialogOption>? = null

val userMutableLiveData = MutableLiveData<ArrayList<ModelDialogOption>>()

init {
    populateList()
    userMutableLiveData.value = list!!
}


private fun populateList() {

    list = ArrayList()

    list!!.add(ModelDialogOption("Prefer not to say", false))
    list!!.add(ModelDialogOption("16-39", false))
    list!!.add(ModelDialogOption("40-59", true))
    list!!.add(ModelDialogOption("60+", false))

}

fun updateItem(position:Int){
    val itemToUpdate = list!!.get(position)
    itemToUpdate.selected = !itemToUpdate.selected!!
    list!![position] = itemToUpdate
}

fun flushItems(){
    userMutableLiveData.value = list!!
}

}

那么从MyDialogFragment中应该是这样的

class MyDialogFragment : DialogFragment(), RecyclerDialogOptionsItem.AdapterListener {

private val viewModel: MainViewModel by activityViewModels()

private lateinit var adapter: GroupAdapter<GroupieViewHolder>
var selectedPosition = -1

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setStyle(STYLE_NO_TITLE, R.style.AppTheme_Dialog_Custom)
}

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

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    rvOptions.layoutManager = LinearLayoutManager(activity)
    adapter = GroupAdapter()
    rvOptions.adapter = adapter


    ivClose.setOnClickListener {

        this.dismiss()
    }


    initViewModel()
}

override fun onDismiss(dialog: DialogInterface) {
    super.onDismiss(dialog)
    viewModel.flushItems()
}

private fun initViewModel() {

    viewModel.userMutableLiveData.observe(this, Observer { list ->
        for (i in list!!) {
            adapter.add(
                RecyclerDialogOptionsItem(
                    this@MyDialogFragment,
                    i,
                    this@MyDialogFragment
                )
            )
        }

    })

}


override fun onClickItem(position: Int) {

    selectedPosition = position
    adapter.notifyDataSetChanged()

    viewModel.updateItem(position)
    Log.i("clicked", "position: $position")
}

}