Убрать проверку элемента интерфейса, если таблица пуста из модели представления - PullRequest
1 голос
/ 23 апреля 2020

Хорошо, я постараюсь сделать это проще. Я пишу приложение, и один из его фрагментов содержит обзор переработчика, который отображает элементы в таблице Room. Когда таблица пуста, я должен отобразить заполнитель.

Я довольно новичок в MVVM, но подход, который я попытался использовать, заключался в добавлении заполнителя в макет (простое текстовое представление) и удалении его из макета, если таблица не пуста. Проблема в том, что каждая попытка определить, пуста ли таблица, не сработала. Я попробовал:

  • Наличие простого запроса в DAO (код ниже) и вызов его в viewmodel. Затем из viewmodel я использую функцию в самом фрагменте. Мне кажется, что этот подход не работает из-за времени выполнения, поскольку функция viewmodel использует сопрограмму для правильной работы
  • Попытка использовать адаптер recyclerview и его метод getItemCount, но всегда возвращает 0

Так что, в основном, я изо всех сил стараюсь просто удалить текстовое представление из макета, когда БД пуста, избегая при этом нарушения принципов MVVM. Вот некоторый полезный код

Функция DAO

@Query("SELECT * FROM Event LIMIT 1")
fun getAnyEvent(): EventResult?

Функция ViewModel

fun getAnyEvent() = viewModelScope.launch(Dispatchers.Default) {
    eventDao.getAnyEvent()
}

Первый не подход

if (homeViewModel.getAnyEvent() != null) {
    val homeMain: LinearLayout = v.findViewById(R.id.homeMain)
    val placeholder: TextView = v.findViewById(R.id.noEvents)
    homeMain.removeView(placeholder)
}

Адаптер

class EventAdapter internal constructor(context: Context) : RecyclerView.Adapter<EventAdapter.EventViewHolder>() {
    private var events = emptyList<EventResult>() // Cached copy of events
    private val appContext = context

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EventViewHolder {
        return EventViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.event_row, parent, false))
    }

    override fun onBindViewHolder(holder: EventViewHolder, position: Int) {
        val current = events[position]
        holder.setUpView(event = current)
    }

    inner class EventViewHolder (view: View) : RecyclerView.ViewHolder(view), View.OnClickListener {
        private val favoriteButton: ImageView = view.favoriteButton
        private val eventPerson: TextView = view.eventPerson
        private val eventDate: TextView = view.eventDate
        private val eventYears: TextView = view.eventYears

        init {
            view.setOnClickListener(this)
        }

        // Set every necessary text and click action in each row
        fun setUpView(event: EventResult?) {
            val personName = event?.name + " " + event?.surname
            val formatter: DateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
            val nextDate = event?.nextDate?.format(formatter)
            val nextAge = appContext.getString(R.string.next_age_years) + ": " + (event?.nextDate?.year?.minus(event.originalDate.year)).toString()
            eventPerson.text = personName
            eventDate.text = nextDate
            eventYears.text = nextAge

        override fun onClick(v: View?) {
            println("test")
        }
    }

    internal fun setEvents(events: List<EventResult>) {
        this.events = events
        notifyDataSetChanged()
    }

    override fun getItemCount() = events.size

}

Какой подход я должен использовать? И что я делаю не так, используя этот шаблон? Как примечание стороны, переработчик работает, и я уже использую liveata, чтобы правильно наблюдать за изменениями.

1 Ответ

1 голос
/ 24 апреля 2020

Казалось, у вас есть только одна потребность - узнать в своем фрагменте, возвращает ли ваш db-запрос 0 или более записей. Вы пытались использовать LiveData для этого (без сопрограмм)? (Вы упоминаете об этом, но это не ясно)

  1. Ваш DAO должен вернуть значение LiveData. К этой комнате "из коробки" будет доставлять к вашему ViewModel фактический результат запроса в онлайн-режиме (конечно, в фоновом потоке).

fun getAnyEvent(): LiveData<List<EventResult>>

В вашей ViewModel вы также можете объявить поле с LiveData

val eventResult: LiveData<List<EventResult>> = eventDao.getAnyEvent()

В своем фрагменте вы просто наблюдаете свой eventResult и можете делать со своим пользовательским интерфейсом все, что захотите, в соответствии с размером списка (если он равен 0, то удалите заглушку View)

homeViewModel.eventResult.observe(viewLifecycleOwner, Observer { eventList -> yourAdapter.setEvents(eventList)})

Здесь - это Codelab от Google со всем этим, например,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...