FirestoreRecyclerAdapter getItemCount () всегда возвращает 0 - PullRequest
0 голосов
/ 29 февраля 2020

Вот мой код класса Адаптера:

class SearchPeopleAdapter(user: FirestoreRecyclerOptions<User>) :
    FirestoreRecyclerAdapter<User, SearchPeopleAdapter.ViewHolder>(user) {

    private var mUser : FirestoreRecyclerOptions<User>? = null

    private var mOptions: FirestoreRecyclerOptions<User>? = null
    private var mSnapshots: ObservableSnapshotArray<User>? = null

    init {
        mUser = user
    }

    fun firestoreRecyclerAdapter(user: FirestoreRecyclerOptions<User>?) {
        mOptions = user
        mSnapshots = user!!.snapshots
        if (mOptions!!.owner != null) {
            mOptions!!.owner!!.lifecycle.addObserver(this)
        }
    }

    override fun startListening() {
        if (!mSnapshots!!.isListening(this)) {
            mSnapshots!!.addChangeEventListener(this);
        }
    }

    override fun stopListening() {
        mSnapshots!!.removeChangeEventListener(this)
        notifyDataSetChanged()
    }

    //Inflate the xml
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(parent.context)
                .inflate(R.layout.search_people_list_item, parent, false))
    }

    //Bind every dataView to the xml based on the Int value
    override fun onBindViewHolder(viewHolder: ViewHolder, holderNumber: Int, user: User) {
        viewHolder.apply {
            itemView.search_people_person_list_name.text = user.Name
            itemView.search_people_person_username.text = user.UserName
        }
        viewHolder.bind(user)
    }

    override fun getItemCount(): Int {
        return mSnapshots!!.size
    }

    //Adds functionality to each View (aka ViewHolder) which is every person downloaded
    inner class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView!!), View.OnClickListener {
        //We are downloading User Objects so this Variable will be assigned to the UserObject downloaded
        var currentUser : User? = null
        //When the class is initiated this function is called which sets an OnClickListener to each View
        init {
            itemView!!.setOnClickListener(this)
        }

        //The Data from the Object is used to Populate the TextViews
        fun bind(model: User) {
            currentUser = model
            itemView.search_people_person_list_name.text = model.Name
            itemView.search_people_person_username.text = model.UserName

            //If the user has set a profilePhoto then download & populate it with Glide
            if ( model.ProfilePhotoChosen ) {
                CompanionObjects.getPersonProfilePhotoStorageRef(model.Uid).downloadUrl.addOnSuccessListener {
                    val downloadUrl = it.toString()
                    Glide.with(itemView)
                        .load(downloadUrl)
                        .into(itemView.search_people_list_profile_image)
                }.addOnFailureListener {
                    Timber.i("unable to retrieve your profile photo")
                }
            }
            //Clear the View with the Glide.with(View).clear() method as the view will be reused and the photo
            //might also get reused unnecessarily
            else {
                Glide.with(itemView).clear(itemView.search_people_list_profile_image)
            }

        }

        //The onClick function is called when the View is clicked, in this case we are starting
        // an Intent with the Intent Extra of userId to the PersonProfile Activity
        // which will check for the IntentExtras and Populate the elements
        override fun onClick(v: View?) {
            val userId = currentUser!!.Uid
            Timber.i("The click is $userId")
            val intent = Intent(v!!.context, PersonProfileActivity::class.java)
            intent.putExtra(CompanionObjects.USER_ID_INTENT_EXTRA, userId)
            v.context.startActivity(intent)
        }

    }

} 

Вот 2 метода в классе Activity. Несмотря на вызов методов onStart и onStop, метод itemCount всегда возвращает 0


    override fun onStop() {
        adapter!!.stopListening()
        super.onStop()
    }

    //Retrieves data from Firestore and assigns the retrieved data to the search People Adapter
    private fun retrieveDataFromFirestore(searchQuery : String) {

        mFirestore = FirebaseFirestore.getInstance()
        //Assigns the Collection Name from which needs to be queried
        //the where conditions ensure to query a userDocument whose userName starts with the query entered in the searchField
        val userNameQuery = mFirestore.collection(CompanionObjects.USERS_COLLECTION_NAME)
            .whereGreaterThanOrEqualTo("userName", searchQuery)
            .whereLessThanOrEqualTo("userName", "$searchQuery\uF7FF")

        //Assigns the query to the User Objects that are related to Firestore
        users = FirestoreRecyclerOptions.Builder<User>()
            .setQuery(userNameQuery, User::class.java)
            .build()

        //Assigns the Firestore queried data to the search People Adapter
        adapter = SearchPeopleAdapter(users!!)
        registerAdapterObserver()
        adapter!!.firestoreRecyclerAdapter(users!!)
        adapter!!.startListening()
        search_people_list.setHasFixedSize(true)
        search_people_list.hasFixedSize()
        search_people_list.layoutManager = LinearLayoutManager(this)
        search_people_list.adapter = adapter
        persistSearchQueryString(searchQuery)

    }

Когда я вызываю метод getItemCount в классе Activity. Он всегда возвращает 0, даже если адаптер действительно удерживает Views. Как получить точное количество в адаптере

Ответы [ 3 ]

0 голосов
/ 29 февраля 2020

В fun retrieveDataFromFirestore(searchQuery : String) после добавления элементов в adapter!!.firestoreRecyclerAdapter(users!!) вы не уведомляете RecyclerView об обновлении.

Итак, не забудьте позвонить

adapter!!.notifyDataSetChanged();

Ваш код может выглядеть следующим образом:

private fun retrieveDataFromFirestore(searchQuery : String) {

    mFirestore = FirebaseFirestore.getInstance()
    //Assigns the Collection Name from which needs to be queried
    //the where conditions ensure to query a userDocument whose userName starts with the query entered in the searchField
    val userNameQuery = mFirestore.collection(CompanionObjects.USERS_COLLECTION_NAME)
        .whereGreaterThanOrEqualTo("userName", searchQuery)
        .whereLessThanOrEqualTo("userName", "$searchQuery\uF7FF")

    //Assigns the query to the User Objects that are related to Firestore
    users = FirestoreRecyclerOptions.Builder<User>()
        .setQuery(userNameQuery, User::class.java)
        .build()

    //Assigns the Firestore queried data to the search People Adapter
    adapter = SearchPeopleAdapter(users!!)
    registerAdapterObserver()
    adapter!!.firestoreRecyclerAdapter(users!!)
    adapter!!.startListening()
    adapter!!.notifyDataSetChanged();  //<------- Add this line---------
    search_people_list.setHasFixedSize(true)
    search_people_list.hasFixedSize()
    search_people_list.layoutManager = LinearLayoutManager(this)
    search_people_list.adapter = adapter
    persistSearchQueryString(searchQuery)

}
0 голосов
/ 12 марта 2020

Хорошо, я решил это, вот код:

private fun retrieveDataFromFirestore(searchQuery : String) {

mFirestore = FirebaseFirestore.getInstance()

 //Assigns the Collection Name from which needs to be queried
        //the where conditions ensure to query a userDocument whose userName 
 starts with the query entered in the searchField
        val userNameQuery = mFirestore.collection(CompanionObjects.USERS_COLLECTION_NAME)
            .whereGreaterThanOrEqualTo(userName, searchQuery.toLowerCase())
            .whereLessThanOrEqualTo(userName, "${searchQuery.toLowerCase()}\uF7FF")

        //Assign the Query to the user variable
        users = FirestoreRecyclerOptions.Builder<User>()
            .setQuery(userNameQuery, User::class.java)
            .build()

//Assigns the Firestore queried data to the search People Adapter
    adapter = object : SearchPeopleAdapter(users!!) {
        //Need to create a class Body because it is open and this gives
        //option to override its onDataChanged method in the Activity rather than in its adapter class
        override fun onDataChanged() {
            if ( itemCount == 0 ) {
                search_people_list.visibility = View.INVISIBLE
                retrieving_progress.visibility = View.INVISIBLE
                empty_search_users_text.visibility = View.VISIBLE
                //If was not searching with name field then prompt search with name field
                if ( !searchingWithNameField ) {
                    //Code to add formatting options to the text like underline it
                    val content = SpannableString(getString(R.string.search_with_name_instead))
                    content.setSpan(UnderlineSpan(), 0, content.length, 0)
                    change_search_field_text.text = content
                } else
                //If was not searching with username field then prompt search with username field
                {
                    //Code to add formatting options to the text like underline it
                    val content = SpannableString(getString(R.string.search_with_username_instead))
                    content.setSpan(UnderlineSpan(), 0, content.length, 0)
                    change_search_field_text.text = content
                }
                change_search_field_text.visibility = View.VISIBLE
            } else {
                //The adapter count is not 0 so show the recyclerView and hide the progress bar, emptyText, Change Search field Text etc.
                search_people_list.visibility = View.VISIBLE
                retrieving_progress.visibility = View.INVISIBLE
                empty_search_users_text.visibility = View.INVISIBLE
                change_search_field_text.visibility = View.INVISIBLE
                //Should persist only if there is a result from the query ofCourse
                persistSearchQueryStringAndSearchField(searchQuery)
            }
        }
    }

    adapterCreated = true
    adapter!!.startListening()
    adapter!!.notifyDataSetChanged()
    //Make the progress bar visible and invisible soon as a document is added to the adapter
    registerAdapterObserver()

    search_people_list.setHasFixedSize(true)
    search_people_list.hasFixedSize()
    search_people_list.layoutManager = LinearLayoutManager(this)
    search_people_list.adapter = adapter

}

Итак, я сделал класс адаптера открытым, а затем создал экземпляр адаптера в Activity и вызвал метод OnDataChanged () в Activity, который отслеживает itemCount в адаптере. Таким образом, я могу получить правильное значение adapterCount.

0 голосов
/ 29 февраля 2020

Пожалуйста, убедитесь, что mSnapshots = пользователь !!. Снимки производит элементы.

...