简体   繁体   English

如果 MutableList 为空,如何更改 TextView 的可见性? (安卓/科特林)

[英]How to change visibility of a TextView if a MutableList is empty? (Android/Kotlin)

I'm working on a simple calorie counter app using two fragments and a ViewModel.我正在使用两个片段和一个 ViewModel 开发一个简单的卡路里计数器应用程序。 I'm a beginner and this is a modification of an app I just created for a course (this app is not a homework assignment).我是初学者,这是对我刚刚为课程创建的应用程序的修改(此应用程序不是家庭作业)。 It uses ViewModel and has a fragment that collects user input and a fragment that displays the input as a MutableList of MutableLiveData.它使用 ViewModel 并有一个用于收集用户输入的片段和一个将输入显示为 MutableLiveData 的 MutableList 的片段。 I would like for the list screen to initially be empty except for a TextView with instructions, and I'd like the instructions to disappear once an entry has been added to the list.我希望列表屏幕最初为空,但带有说明的 TextView 除外,并且一旦将条目添加到列表中,我希望说明消失。 My class instructor told me to use an if-else statement in the fragment with the list to achieve this, but it's not working.我的班主任告诉我在带有列表的片段中使用 if-else 语句来实现这一点,但它不起作用。 He didn't tell me exactly where to put it.他没有告诉我确切地把它放在哪里。 I tried a bunch of different spots but none of them worked.我尝试了很多不同的地方,但没有一个有效。 I don't get errors - just no change to the visibility of the TextView.我没有收到错误 - 只是 TextView 的可见性没有改变。

Here is the code for the ViewModel with the list:这是带有列表的 ViewModel 的代码:

    val entryList: MutableLiveData<MutableList<Entry>>
        get() = _entryList

 init {
     _entry = MutableLiveData<Entry>()
     _entryList.value = mutableListOf()
    }

    fun addEntry(entryInfo: Entry){
        _entry.value = entryInfo
        _entryList.value?.add(_entry.value!!)
    }
}

And this is the code for the observer in the list fragment:这是列表片段中观察者的代码:

                Observer  { entryList ->
                    val entryListView: View = inflater.inflate(R.layout.fragment_entry_list, null, false)
                    if (entryList.isNullOrEmpty()) {
                        entryListView.instructions_text_view.visibility = View.VISIBLE
                    } else {
                        entryListView.instructions_text_view.visibility = View.GONE
                    }

                    entryList.forEach {entry ->
                    val view: View = inflater.inflate(R.layout.entry_list_item, null, false)
                    view.date_entry_text_view.text = String.format(getString(R.string.date), entry.date)
                    view.calories_entry_text_view.text =
                    view.line_divider
                    binding.entryList.addView(view)
                 }

Thanks for any help.谢谢你的帮助。

I guess you are expecting your observer to get notified of the event when you are adding entryInfo to your event list ( _entryList.value?.add(_entry.value!!) . But this won't happen as you are just adding an element to the same mutable list, and as the list reference hasn't changed, live data won't emit any update.我猜您希望您的观察者在您将entryInfo添加到您的事件列表 ( _entryList.value?.add(_entry.value!!)时会收到该事件的通知。但这不会发生,因为您只是添加了一个元素到同一个可变列表,并且由于列表引用没有改变,实时数据不会发出任何更新。

To solve this, you have two options.要解决此问题,您有两种选择。

  • Create a new boolean live data which controls when to show and hide the info text.创建一个新的布尔实时数据,用于控制何时显示和隐藏信息文本。 Set its initial value to false , and update it to true in addEntry() function.将其初始值设置为false ,并在addEntry()函数addEntry()其更新为true
  • Instead of updating the same mutable list, create of copy of it, add the element and set the entryList.value equal to this new list.不是更新相同的可变列表,而是创建它的副本,添加元素并将 entryList.value 设置为等于这个新列表。 This way your observer will be notified of the new list.这样你的观察者就会收到新列表的通知。

Additionally, its generally not a good practice to expose mutable data unless there is no alternative.此外,除非别无选择,否则公开可变数据通常不是一个好习惯。 Here you are exposing a mutable list of Entry and that too in the form of a mutable live data.在这里,您将公开一个可变的 Entry 列表,并且也以可变的实时数据的形式公开。 Ideally, your should be exposing LiveData<List<Entry>> .理想情况下,您应该公开LiveData<List<Entry>>

This is one possible implementation of all the points that I mentioned:这是我提到的所有要点的一种可能实现:

private val _entryList = MutableLiveData(listOf<Entry>()) // Create a private mutable live data holding an empty entry list, to avoid the initial null value.
val entryList: LiveData<List<Entry>> = _entryList // Expose an immutable version of _entryList

fun addEntry(entryInfo: Entry) {
    _entryList.value = entryList.value!! + entryInfo
}

I haven't used the _entry live data here, but you can implement it the same way.我这里没有使用_entry实时数据,但你可以用同样的方式实现它。

set your viewModel to observe on entry added.将您的 viewModel 设置为在添加条目时观察。

I think you have gotten your visibility toggle in the your if else blocks wrong.我认为您在 if else 块中设置了可见性切换错误。

if (entryList.isNullOrEmpty()) {
       entryListView.instructions_text_view.visibility = View.GONE // OR View.INVISIBLE
} else {
       entryListView.instructions_text_view.visibility = View.VISIBLE
}

Your Observer should get notified of changes to entryList when _entryList has changed.当 _entryList 发生变化时,您的观察者应该收到 entryList 变化的通知。 Make sure you are calling addEntry() function to trigger the notification.确保您正在调用 addEntry() 函数来触发通知。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM