У меня есть база данных 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 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
    }
}

Наконец, если вам это нужно, вот вспомогательная сущность - класс Restaurant Item:

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 в порядке, и время, дата и количество гостей отображаются правильно.

Класс restaurant работает, потому что он используется где-то еще и правильно отображается в других представлениях ресайклера.

Проблема, по-видимому, в том, что при создании экземпляра элемента бронирования все данные в элементе ресторана устанавливаются в нулевые значения.

Я прошел через отладчик и вижу, что данные были получены из firebase.

Это данные, когда я отлаживаю конструктор bookingitem и прохожу через

Здесь данные теряются и сбрасываются до нулевых значений:

Вот строка, что данные потеряны

Вы можете получить доступ к коду здесь https://github.com/KotaCanchela/RestaurantBookingSystem

Я ценю любую помощь, которая может быть предоставлена, я постарался дать как можно больше подробностей.

0
Ali P 18 Мар 2021 в 23:05

2 ответа

Лучший ответ

Когда вы отлаживаете свой код, все свойства объекта «restaurantItem» в отладчике сохраняют значения по умолчанию, потому что нет соответствия между объектом класса и объектом в Firestore.

Ваш класс BookingItem содержит свойство с именем restaurantItem, тогда как в базе данных объект называется только "ресторан", что неверно. Оба имени должны совпадать. Вы либо измените имя свойства в базе данных на «restaurantItem», а не просто «ресторан», либо используйте следующие аннотации:

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

Перед вашим свойством restaurantItem в вашем классе BookingItem.

Изменить:

Согласно вашему комментарию:

вы имеете в виду в конструкторе BookingItem?

Да. Минимальная реализация для вашего класса может быть:

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. Получив данные из базы данных, вы присваиваете значения своим фактическим полям.

0
Alex Mamo 19 Мар 2021 в 17:27

Пожалуйста, дайте ему учетные данные пользователя, вошедшего в систему ...

-1
axar 19 Мар 2021 в 13:48