Попытка получить данные облачной базы данных Firebase и отобразить их в окне RecyclerView во фрагменте

# #android #firebase #kotlin #google-cloud-firestore #android-recyclerview

Вопрос:

Я пытаюсь получить свои данные в RecyclerView облачном хранилище данных Firebase. Но когда я это делаю, я получаю следующую ошибку:

исключение java.lang.RuntimeException: Не удалось десериализовать объект. Классные модели.Post не определяет конструктор без аргументов. Если вы используете ProGuard, убедитесь, что эти конструкторы не удалены

Это фрагмент, который я использую:

 class forumFragment : Fragment(R.layout.fragment_forum)  {

    private lateinit var myadapter: MyAdapter

    private lateinit var fragmentForumBinding: FragmentForumBinding

    private lateinit var userArrayList: ArrayList<itemViewModel>
    private lateinit var postDao: postDao



    //val mAuth= Firebase.auth.currentUser
    val mAuth : FirebaseUser? = FirebaseAuth.getInstance().currentUser

    //private lateinit var recyclerView:RecyclerView



    private var mDocReference: DocumentReference ?=null
    //= FirebaseFirestore.getInstance().collection(/).document()
    /*override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
       // recyclerView = view?.findViewById(R.id.recyclerViewForum)!!
        val binding = FragmentForumBinding.inflate(layoutInflater)
        fragmentForumBinding = binding

        setUpRecyclerView()
    }*/

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val binding = FragmentForumBinding.bind(view)
        fragmentForumBinding = binding

        setUpRecyclerView()
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val view: View = inflater.inflate(R.layout.fragment_forum, container, false)

        val fabButtom = view.findViewById<FloatingActionButton>(R.id.fabSave)

        fabButtom.setOnClickListener{
            if (mAuth !=null){
                fabButtom.visibility = View.INVISIBLE
                fragmentManager?.beginTransaction()?.addToBackStack(null)?.replace(R.id.forumFragment , addPost())?.commit()
                //val navControl = findNavController(R.id.forumFragment)
            }
            else{
             Toast.makeText(activity ,"Please login to make a query!" , Toast.LENGTH_SHORT).show()
            }

        }

        return view

        }

    private fun setUpRecyclerView() {

       // val recyclerView = view?.findViewById<RecyclerView>(R.id.recyclerViewForum)
        postDao = postDao()

        val postsCollection = postDao.postCollection
        val query = postsCollection.orderBy("createdAt" , Query.Direction.DESCENDING)
        val firestoreRecyclerOptions = FirestoreRecyclerOptions.Builder<Post>().setQuery(query , Post::class.java).build()

        myadapter = MyAdapter(firestoreRecyclerOptions)



        fragmentForumBinding.recyclerViewForum.adapter = myadapter
        fragmentForumBinding.recyclerViewForum.layoutManager = LinearLayoutManager(activity)

    }

    override fun onStart() {
        super.onStart()

        myadapter.startListening()
    }

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

и models.Post класс выглядит так:

 data class Post (val descrription: String = "",
                 val createdBy: User = User(),

                 val  currentTime:String = "",
                 val currentDate:String = "",
                 val createdAt:Long )
 

Комментарии:

1. Неясно, используете ли вы Cloud Firestore (по умолчанию), Cloud Firestore в режиме Datatore или Базу данных реального времени, поскольку вы используете эти термины взаимозаменяемо.

2. В будущем при форматировании блоков кода вам нужно будет использовать символ обратной стрелки ` (обычно на клавише тильды ~ ) вместо апострофа ' . Один обратный отсчет для встроенного кода, три обратных отсчета (в отдельной строке) для блоков кода.

Ответ №1:

Чтобы Firebase SDK мог преобразовать удаленные данные в нужный класс модели, у него должен быть конструктор без аргументов.

Примечание: Я исправил descrription description ниже.

В вашем текущем models.Post классе у него нет значения по умолчанию для createdAt :

 data class Post (val description: String = "",
                 val createdBy: User = User(),
                 val currentTime: String = "",
                 val currentDate: String = "",
                 val createdAt: Long ) // <-- missing = 0L
 

Так и должно быть:

 data class Post (val description: String = "",
                 val createdBy: User = User(),
                 val currentTime: String = "",
                 val currentDate: String = "",
                 val createdAt: Long = 0L )
 

В качестве альтернативы вы можете иметь следующее объявление для models.Post :

 data class Post (val description: String,
                 val createdBy: User,
                 val currentTime: String,
                 val currentDate: String,
                 val createdAt: Long) {
  // empty constructor for Firebase with dummy data
  constructor(): this("", User(), "", "", 0L)
}