簡體   English   中英

使用 Firestore Kotlin RecyclerView,我試圖顯示一個自定義 object,它是 class 的一個字段,顯示在回收站視圖中

[英]Working with a Firestore Kotlin RecyclerView, I am trying to show a custom object which is a field of the class being displayed in the recycler view

我有一個保存我的數據的 Firestore 數據庫。 這是結構(數據庫結構

子類數據庫結構

所以我的預訂是用戶的子集合。 每個預訂都包含自己的餐廳作為子文檔。

這是活動文件:


    private lateinit var binding: ActivityMyBookingsBinding

    //recyclerview for list
    lateinit var recyclerView: RecyclerView

    //Firestore
    private var currentUser: FirebaseUser = FirebaseAuth.getInstance().currentUser!!
    private var db: FirebaseFirestore = FirebaseFirestore.getInstance()

    var query: CollectionReference = db
        .collection("Users")
        .document(currentUser.uid)
        .collection("Bookings")

    //adapter
    lateinit var bookingAdapter: BookingItemAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)


        binding = ActivityMyBookingsBinding.inflate(layoutInflater)
        val view = binding.root
        setupUI()
        setContentView(view)


        setupRecyclerView()
    }


    private fun setupUI() {
        recyclerView = binding.bookingList
    }


    private fun setupRecyclerView(){

        val options: FirestoreRecyclerOptions<BookingItem> = FirestoreRecyclerOptions.Builder<BookingItem>()
            .setQuery(query, BookingItem::class.java)
            .build()

        bookingAdapter = BookingItemAdapter(this, options)

        recyclerView.layoutManager = LinearLayoutManager(this)

        recyclerView.adapter = bookingAdapter

    }

    override fun onStart() {
        super.onStart()
        bookingAdapter.startListening()
    }

    override fun onStop() {
        super.onStop()
        bookingAdapter.stopListening()
    }

這是適配器文件

class BookingItemAdapter(
    val context: Context,
    val options: FirestoreRecyclerOptions<BookingItem>): FirestoreRecyclerAdapter<BookingItem, BookingItemAdapter.BookingViewHolder>(options) {








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

    @RequiresApi(Build.VERSION_CODES.N)
    override fun onBindViewHolder(holder: BookingViewHolder, position: Int, model: BookingItem) {
        holder.restaurantNameText.booking_restaurant_name.text = model.getRestaurantItem().getName()
        holder.restaurantDistanceText.booking_distance.text = model.getRestaurantItem().getGeoHash()
        holder.restaurantRatingBar.booking_ratingBar.rating = model.getRestaurantItem().getRating()?.toFloat()!!
        holder.bookingDate.booking_date.text = "${model.getDay()}/${model.getMonth()}/${model.getYear()}"
        holder.bookingTime.booking_time.text = "${model.getHour()}:${model.getMinute()}"
        holder.numberGuests.number_guests.text = model.getGuestNumber()

        val url = model.getRestaurantItem().getRestaurantImage()
        Glide
            .with(holder.restaurantImageItem)
            .load(url)
            .into(holder.restaurantImageItem.booking_restaurantImage)

        holder.itemView.setOnClickListener {
            val intent = Intent(context, RestaurantPageActivity::class.java)
            intent.putExtra("model", model.getRestaurantItem())

            context.startActivity(intent)

        }

        CompletableFuture.runAsync {
            runCatching {
                val url = model.getRestaurantItem().getRestaurantImage()
                Glide
                    .with(holder.restaurantImageItem)
                    .load(url)
                    .into(holder.restaurantImageItem.booking_restaurantImage)

            }
        }
    }

    inner class BookingViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val restaurantNameText: TextView = itemView.findViewById(R.id.booking_restaurant_name)
        val restaurantImageItem: ImageView = itemView.findViewById(R.id.booking_restaurantImage)
        val restaurantRatingBar: RatingBar = itemView.findViewById(R.id.booking_ratingBar)
        val restaurantDistanceText: TextView = itemView.findViewById(R.id.booking_distance)
        val bookingTime: TextView = itemView.findViewById(R.id.booking_time)
        val bookingDate: TextView = itemView.findViewById(R.id.booking_date)
        val numberGuests: TextView = itemView.findViewById(R.id.number_guests)

    }

這是 bookingItem class:

class BookingItem(restaurantItem: RestaurantItem, guestNumber: String, day: String,
                  month: String, year: String, hour: String, minute: String) {

    constructor(): this(RestaurantItem("", "", 0, 0,
            "", "", "", "", false), "", "", "", "", "","")

    private var restaurantItemName = restaurantItem.getName()
    private var restaurantItemImage = restaurantItem.getRestaurantImage()
    private var restaurantItemPrice = restaurantItem.getPrice()
    private var restaurantItemRating = restaurantItem.getRating()
    private var restaurantItemGeohash = restaurantItem.getGeoHash()
    private var restaurantItemLongitude = restaurantItem.getLongitude()
    private var restaurantItemLatitude = restaurantItem.getLatitude()
    private var restaurantItemCuisine = restaurantItem.getCuisine()
    private var restaurantItemDietary = restaurantItem.getDietaryFriendly()
    private var restaurantItem: RestaurantItem = RestaurantItem(
            restaurantItemName,
            restaurantItemImage,
            restaurantItemPrice,
            restaurantItemRating,
            restaurantItemGeohash,
            restaurantItemLongitude,
            restaurantItemLatitude,
            restaurantItemCuisine,
            restaurantItemDietary)

    private var guestNumber: String = guestNumber
    private var day: String = day
    private var month: String = month
    private var year: String = year
    private var hour: String = hour
    private var minute: String = minute



    fun getRestaurantItem(): RestaurantItem{
        this.restaurantItem.getName()
        this.restaurantItem.getRestaurantImage()
        this.restaurantItem.getPrice()
        this.restaurantItem.getRating()
        this.restaurantItem.getGeoHash()
        this.restaurantItem.getLongitude()
        this.restaurantItem.getLatitude()
        this.restaurantItem.getCuisine()
        this.restaurantItem.getDietaryFriendly()
        return this.restaurantItem
    }
    fun getGuestNumber(): String {
        return this.guestNumber
    }

    fun getDay(): String{
        return this.day
    }

    fun getMonth(): String{
        return this.month
    }

    fun getYear(): String{
        return this.year
    }

    fun getHour(): String{
        return this.hour
    }

    fun getMinute(): String{
        return this.minute
    }
}

最后,如果您需要它,這里是子實體 - restaurantItem class:

class RestaurantItem(name: String, restaurantImage: String, price: Long, rating: Long, geoHash: String ,
                     longitude: String, latitude: String, cuisine: String, dietaryFriendly: Boolean): Parcelable{

    constructor(): this ("", "", 0, 0,
        "", "", "", "", false
    )


    private var name: String = name
    private var restaurantImage: String = restaurantImage
    private var price: Long = price
    private var rating: Long = rating
    private var geoHash: String = geoHash
    private var longitude: String = longitude
    private var latitude: String = latitude
    private var cuisine: String = cuisine
    private var dietaryFriendly: Boolean = dietaryFriendly

    private constructor(parcel: Parcel) : this() {
        name = parcel.readString().toString()
        restaurantImage = parcel.readString().toString()
        price = parcel.readLong()
        rating = parcel.readLong()
        geoHash = parcel.readString().toString()
        longitude = parcel.readString().toString()
        latitude = parcel.readString().toString()
        cuisine = parcel.readString().toString()
        dietaryFriendly = parcel.readByte() != 0.toByte()
    }


    fun getName(): String {
        return this.name
    }
    fun getLatitude(): String {
        return this.latitude
    }
    fun getLongitude(): String {
        return this.longitude
    }
    fun getGeoHash(): String {
        return this.geoHash
    }
    fun getPrice(): Long {
        return this.price
    }
    fun getDietaryFriendly(): Boolean{
        return this.dietaryFriendly
    }
    fun getRating(): Long {
        return this.rating
    }
    fun getRestaurantImage(): String {
        return this.restaurantImage
    }
    fun getCuisine(): String {
        return this.cuisine
    }
    

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(name)
        parcel.writeString(restaurantImage)
        parcel.writeLong(price)
        parcel.writeLong(rating)
        parcel.writeString(geoHash)
        parcel.writeString(longitude)
        parcel.writeString(latitude)
        parcel.writeString(cuisine)
        parcel.writeByte(if (dietaryFriendly) 1 else 0)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<RestaurantItem> {
        override fun createFromParcel(parcel: Parcel): RestaurantItem {
            return RestaurantItem(parcel)
        }

        override fun newArray(size: Int): Array<RestaurantItem?> {
            return arrayOfNulls(size)
        }
    }

現在數據從 firebase 進來,時間、日期和客人數量都顯示正確。

餐廳 class 之所以有效,是因為它在其他地方使用並在其他回收站視圖中正確顯示。

問題似乎是,當預訂項目被實例化時,restaurantItem 中的所有數據都設置為其 null 值。

我使用調試器進行了檢查,我可以看到數據來自 firebase。

這是我在 bookingitem 構造函數中調試並逐步執行時的數據

這是數據丟失並重置為 null 值的地方:

這是數據丟失的行

您可以在此處訪問代碼https://github.com/KotaCanchela/RestaurantBookingSystem

我感謝可以提供的任何幫助,我已嘗試在此處提供盡可能多的詳細信息。

When you are debugging your code, all the properties of the "restaurantItem" object in the debugger are holding the default values because there is no match between the object of the class and the object in Firestore.

您的“BookingItem” class 擁有名為“restaurantItem”的屬性,而在數據庫中 object 僅稱為“restaurant” ,這是不正確的。 兩個名稱必須匹配。 您可以將數據庫中的屬性名稱更改為“restaurantItem”而不僅僅是“restaurant”,或者您應該使用以下注釋:

@get:PropertyName("restaurant")
@set:PropertyName("restaurant")
@PropertyName("restaurant")

在“BookingItem”class 中的restaurantItem屬性前面。

編輯:

根據您的評論:

你的意思是在 BookingItem 構造函數中嗎?

是的。 class 的最低實現可能是:

data class BookingItem(
        @get:PropertyName("restaurant")
        @set:PropertyName("restaurant")
        @PropertyName("restaurant")
        var restaurantItem: RestaurantItem? = null,
        var guestNumber: String? = null,
        var day: String? = null,
        var month: String? = null,
        var year: String? = null,
        var hour: String? = null,
        var minute: String? = null
)

我用null值初始化了這些對象。 從數據庫中獲取數據后,您會將值分配給您的實際字段。

暫無
暫無

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

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