Home > Mobile >  Trying to notify adapter that item added after getting data from fire store
Trying to notify adapter that item added after getting data from fire store

Time:10-20

inside MainActivity I have snapShot listener to document added that calls a function inside a fragment that supose to set and update the adapter of item that stored in fire store

mFireStore.collection(Constans.BOARDS)
            .whereArrayContains(Constans.ASSIGNED_TO,FireStore().getCurrentUid())
            .orderBy("timeStamp", Query.Direction.DESCENDING)
            .addSnapshotListener { value, e ->
                Log.d("MainActivity","board listener")
                if (e != null) {
                    Log.w(ContentValues.TAG, "Listen failed.", e)
                    return@addSnapshotListener
                }

                val boards = ArrayList<Board>()

                Constans.BOARDS_CHATS_LIST = ArrayList()
                for (doc in value!!) {
                    val board = doc.toObject(Board()::class.java)
                    Constans.BOARDS_CHATS_LIST.add(board)

                }
              fragment_chat().updateBoardToUi(Constans.BOARDS_CHATS_LIST)
}

and here is the function

fun updateBoardToUi(boardsChatsList: ArrayList<Board>) {
        if(boardsChatsList.size > 0){

            val context = getContext() ?: return
            Log.e("${Constans.BOARDS_CHATS_LIST.size.toString()}","updateBoardToUi")
            view?.rv_chats_list?.visibility = View.VISIBLE
            view?.no_chats_avlible?.visibility = View.GONE

            view?.rv_chats_list?.layoutManager = LinearLayoutManager(context)
            view?.rv_chats_list?.setHasFixedSize(true)
//might be an error
             adapter = BoardItemsAdapter(context,Constans.BOARDS_CHATS_LIST)
            
            view?.rv_chats_list?.adapter = adapter
            adapter.notifyItemInserted(0)



            adapter.setOnClickListener(
                object :BoardItemsAdapter.OnClickListener{
                    override fun onClick(position: Int, model: Board) {
                        Log.i("fragment chat", "on click")
                        val intent = Intent(context, ChatActivity::class.java)

                        intent.putExtra(Constans.BOARD_CHAT_DETAILS, model)
                        intent.putExtra("uid", FirebaseAuth.getInstance().currentUser?.uid )
                        intent.putExtra(Constans.DOCUMENT_ID, model.documentId)
                        intent.putExtra("position", position)

                        startActivity(intent)
                    }
                }
            )
        }else{

            Log.e("inside","updateBoardToUi2")
            view?.no_chats_avlible?.visibility = View.VISIBLE
        }
    }

but the adapter deas not show the new item added even thogh I use adapter.notifyItemInserted(0)

CodePudding user response:

It is because you can not hold and send data with "Constants.BOARDS_CHATS_LIST". Because every time you want to call it, it will return the default value it has. You can do 4 things that come into my mind:
1- Send the data from activity to fragment via Shared Preferences. I do not recommend this method.
2 - Send data from activity to fragment via bundle. This is doable but i do not prefer it.
3 - Move your firestore function to the fragment and declare a global list and put the records there, then use it in updateBoardToUi function. You can do this but if you need this function in other fragment, you need to copy and paste it there too.
4- You can create a new class for firestore functions, and whenever you need it, call it from there. This is the best way and i will try to help you with it.
Create new kotlin class and paste this inside it. You will later call this inside onViewCreated of your fragment, and it will send the array to the updateBoardToUi method.

class FirestoreClass {
    private val mFireStore = FirebaseFirestore.getInstance()
    private val mFirebaseAuth = FirebaseAuth.getInstance()

    fun getBoards(fragment: YourFragmentName) {
        mFireStore.collection(Constans.BOARDS)
            .whereArrayContains(Constans.ASSIGNED_TO,getCurrentUserID())
            .orderBy("timeStamp", Query.Direction.DESCENDING)
            .addSnapshotListener { value, e ->
                if (e != null) {
                    Log.w(ContentValues.TAG, "Listen failed.", e)
                    return@addSnapshotListener
                }

                val boards = ArrayList<Board>()

                for (doc in value!!) {
                    val board = doc.toObject(Board()::class.java)
                    boards.add(board)

                }
                fragment.updateBoardToUi(boards)
            }

    }

    fun getCurrentUserID(): String {
           val currentUser = mFirebaseAuth.currentUser
           var currentUserID = ""
           if (currentUser != null) {
               currentUserID = currentUser.uid
           }
           return currentUserID
    }
}

Now we will use the list from your db.

fun updateBoardToUi(boardsChatsList: ArrayList<Board>) {
        // fragment.updateBoardToUi(boards) that sent the data and now 
        // it is in boardsChatsList, you will use this.
        if(boardsChatsList.size > 0){

            val context = getContext() ?: return
            Log.e("${boardsChatsList.size.toString()}","updateBoardToUi")
            view?.rv_chats_list?.visibility = View.VISIBLE
            view?.no_chats_avlible?.visibility = View.GONE

            adapter = BoardItemsAdapter(context,boardsChatsList)
            view?.rv_chats_list?.adapter = adapter
            view?.rv_chats_list?.layoutManager = LinearLayoutManager(context)
            view?.rv_chats_list?.setHasFixedSize(true)         

            adapter.setOnClickListener(
                object :BoardItemsAdapter.OnClickListener{
                    override fun onClick(position: Int, model: Board) {
                        Log.i("fragment chat", "on click")
                        val intent = Intent(context,ChatActivity::class.java)

                        intent.putExtra(Constans.BOARD_CHAT_DETAILS, model)
                        intent.putExtra("uid", FirestoreClass().getCurrentUserID())
                        intent.putExtra(Constans.DOCUMENT_ID, model.documentId)
                        intent.putExtra("position", position)

                        startActivity(intent)
                    }
                }
            )
        }else{

            Log.e("inside","updateBoardToUi2")
            view?.no_chats_avlible?.visibility = View.VISIBLE
        }
    }

And finally call that db function in your fragment's onViewCreated to activate all of this. If you do not have onViewCreated just paste this code:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState) 
        
        FirestoreClass().getUsersList(this)
}

All of this can be too much, but this is the best practice. If you learn this convention, you will easily adapt working anywhere.

  • Related