簡體   English   中英

Android recycler查看和數據綁定

[英]Android recyclerView and data binding

我在 Kotlin 中創建了一個 Android 應用程序,我想從網絡服務器獲取一些信息並使用數據綁定放入回收站視圖。 我使用存儲庫模式,所以每次我發出獲取請求時,我都會將信息保存在房間數據庫中,並使用實時數據從中獲取數據。 出於某種原因,我的 ryclerview 沒有顯示任何內容,並且我沒有收到任何錯誤。 請求有效,我得到了數據,但 recyclerview 不起作用。 我的視圖模型:

class HomeViewModel(application: Application) : ViewModel() {
    private val availableTicketsRepo = AvailableTicketsRepository(getInstance(application))

    val tickets = availableTicketsRepo.availableTickets

    init {
        refreshDataFromRepository()
    }

    private fun refreshDataFromRepository() {
        viewModelScope.launch {
            try {
                availableTicketsRepo.refreshAvailableTickets()
            } catch (ex: Exception) {
                ex.message?.let { Resource.error(data = null, message = it) }
                Log.i("Home", "*** Eccezione: ${ex} ***")
            }
        }
    }

我的片段 class (帶適配器和視圖):

package com.example.ticketapp.ui.home

class HomeFragment : Fragment() {

    private val viewModel: HomeViewModel by lazy {
        val activity = requireNotNull(this.activity) {
            "You can only access the viewModel after onActivityCreated()"
        }
        ViewModelProvider(this, HomeViewModel.Factory(activity.application))
            .get(HomeViewModel::class.java)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val binding = DataBindingUtil.inflate<FragmentHomeBinding>(
            inflater,
            R.layout.fragment_home,
            container,
            false
        )

        binding.lifecycleOwner = this
        binding.viewModel = viewModel

        binding.availableTicketsList.adapter = AvailableTicketsAdapter()


        return binding.root
    }
}

class AvailableTicketsAdapter() :
    ListAdapter<AvailableTicket, AvailableTicketsAdapter.AvailableTicketViewHolder>(DiffCallback) {

    class AvailableTicketViewHolder(private var binding: AvailableTicketItemsBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(tickets: AvailableTicket) {
            binding.ticket = tickets
            binding.executePendingBindings()
        }
    }

    companion object DiffCallback : DiffUtil.ItemCallback<AvailableTicket>() {
        override fun areItemsTheSame(oldItem: AvailableTicket, newItem: AvailableTicket): Boolean {
            return oldItem === newItem
        }

        override fun areContentsTheSame(
            oldItem: AvailableTicket,
            newItem: AvailableTicket
        ): Boolean {
            return oldItem.Id == newItem.Id
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AvailableTicketViewHolder {
        return AvailableTicketViewHolder(
            AvailableTicketItemsBinding.inflate(
                LayoutInflater.from(
                    parent.context
                )
            )
        )
    }


    override fun onBindViewHolder(holder: AvailableTicketViewHolder, position: Int) {
        val tickets = getItem(position)
        holder.bind(tickets)
    }
}

我的存儲庫:

class AvailableTicketsRepository(private val database: TicketDatabase) {
    val availableTickets: LiveData<List<AvailableTicket>> =
        Transformations.map(database.ticketDatabaseDao.getAvailableTickets()) {
            it.asDomainModel()
        }


    suspend fun refreshAvailableTickets() {
        withContext(Dispatchers.IO) {
            val tickets = RetrofitBuilder.apiService.getAvailableTickets()
            database.ticketDatabaseDao.insertAllAvailableTickets(tickets.map { it.asDataBaseModel() })
        }
    }
}

recyclerview 中項目的 xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="android.view.View"/>
        <variable
            name="ticket"
            type="com.example.ticketapp.model.AvailableTicket" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/titleText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLength="50"
            android:text="@{ticket.title}"
            android:singleLine="true"
            android:textAlignment="center"
            android:textSize="16sp"
            android:textStyle="bold"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="Titolo di max 50 caratteri per non uscire dalla riga" />


        <TextView
            android:id="@+id/customerText"
            android:layout_width="160dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:textSize="14sp"
            android:text="@{ticket.customer}"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/titleText"
            tools:text="ESEMPIO DI UN REFERENTE" />

        <TextView
            android:id="@+id/dateText"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:textAlignment="textEnd"
            android:textSize="14sp"
            android:text="@{ticket.date_Time}"
            app:layout_constraintBaseline_toBaselineOf="@+id/customerText"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/titleText"
            tools:text="20/01/2021 10:00:00" />

        <ImageView
            android:id="@+id/warningImg"
            style="@style/iconImg"
            android:layout_marginTop="20dp"
            android:visibility="@{ticket.triangle ? View.VISIBLE : View.GONE}"
            android:foregroundGravity="center"
            app:layout_constraintEnd_toStartOf="@+id/dateText"
            app:layout_constraintStart_toEndOf="@+id/customerText"
            app:layout_constraintTop_toBottomOf="@+id/titleText"
            app:srcCompat="@drawable/ic_warning" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

ryclerview的XML:

<androidx.recyclerview.widget.RecyclerView
           android:id="@+id/availableTicketsList"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:paddingStart="10dp"
           android:paddingEnd="10dp"
           app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
           app:layout_constraintEnd_toEndOf="parent"
           app:layout_constraintStart_toStartOf="parent"
           app:layout_constraintTop_toBottomOf="@+id/toolbar"
           tools:listitem="@layout/available_ticket_items" />

我的 Model class:

@Parcelize
data class AvailableTicket (
   val Id: Int,
   val Title: String,
   val Description: String,
   val Date_Time: String,
   val Customer: String,
   val Field: String,
   val Category: String,
   val Color: String,
   val Author: String,
   val Triangle: Boolean,
   val MyPriority: String
): Parcelable

您應該在修改數據時通知適配器,在ViewModel中添加LiveData並將其發布在availableTicketsRepo.refreshAvailableTickets()之后,然后在收到數據后調用適配器內部的submitList

視圖模型

class HomeViewModel(application: Application) : ViewModel() {
    private val availableTicketsRepo = AvailableTicketsRepository(getInstance(application))
    val tickets = availableTicketsRepo.availableTickets

    init {
        refreshDataFromRepository()
    }

    private fun refreshDataFromRepository() {
        viewModelScope.launch {
            try {
                availableTicketsRepo.refreshAvailableTickets()
            } catch (ex: Exception) {
                ex.message?.let { Resource.error(data = null, message = it) }
                Log.i("Home", "*** Eccezione: ${ex} ***")
            }
        }
    }
}

然后在Fragment中,將列表提交給適配器一旦獲取

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val binding = DataBindingUtil.inflate<FragmentHomeBinding>(
            inflater,
            R.layout.fragment_home,
            container,
            false
        )

        binding.lifecycleOwner = this
        binding.viewModel = viewModel

        binding.availableTicketsList.adapter = AvailableTicketsAdapter()

        viewModel.tickets.observe(this, Observer{
            (binding.availableTicketsList.adapter as? AvailableTicketsAdapter)?.submitList(it)
        })
        return binding.root
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM