При добавлении записи в Cloud Firestore, в приложении записи появляются в случайном порядке. Как сделать, чтобы записи появлялись по хронологии?

Есть простое приложение (To-Do) использующее для хранения записей Cloud Firestore (Firestore Database). При добавлении записи, в приложении записи появляются в случайном порядке. Как я понял, записи располагаются согласно неким ID, автоматически присваиваемым Cloud Firestore каждой записи (документу). Как сделать так, чтобы записи располагались в хронологическом порядке?

FirestoreRepository.kt

    class FirestoreRepositoryImpl @Inject constructor(
    private val firebaseFirestore: FirebaseFirestore,
    private val auth: FirebaseAuth
) : FirestoreRepository {

    override suspend fun createNote(note: Note) {
        auth.uid?.let {
            firebaseFirestore.collection(USERS).document(USERS).collection(NOTES).add(note).await()
            
        }
    }

    override suspend fun getNotes(): ArrayList<Note> {
        val noteList: ArrayList<Note> = arrayListOf()
        val def = CompletableDeferred<ArrayList<Note>>()
        auth.uid?.let { uid ->
            firebaseFirestore.collection(USERS).document(USERS).collection(NOTES)
                .get()
                .addOnCompleteListener {
                    if (it.isSuccessful) it.result.let { note ->
                        val notesDocuments = note.documents
                        notesDocuments.forEach { noteDocument ->
                            val note = Note(noteDocument.id, noteDocument.getString("title"), noteDocument.getString("description"), noteDocument.getString("date"))
                            noteList.add(note)
                        }
                        def.complete(noteList)
                    }
                }
        }
        return def.await()
    }

    override suspend fun updateNote(note: Note) {
        auth.uid?.let {
            note.id?.let { it1 ->
                firebaseFirestore.collection(USERS).document(USERS).collection(NOTES).document(it1)
                    .update(mapOf(
                        "title" to note.title,
                        "description" to note.description
                    )).await()
            }
        }
    }

    override suspend fun deleteNote(docId: String) {
        auth.uid?.let {
            firebaseFirestore.collection(USERS).document(USERS).collection(NOTES).document(docId)
                .delete().await()
        }
    }

}

HomeFragment.kt

class HomeFragment : Fragment() {

    private lateinit var binding: FragmentHomeBinding
    private lateinit var notesList: ArrayList<Note>
    private lateinit var date: Date

    @Inject
    lateinit var auth: FirebaseAuth
    private val homeViewModel: HomeViewModel by viewModels()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentHomeBinding.inflate(inflater)

        binding.tvWelcome.text =
            "Welcome ${SharedPreferences(requireContext()).getUsernameString()}!"
        initListeners()
        getNotes()
        onBackPressed()
     
        return binding.root
    }

    private fun initListeners() {
        with(binding) {
            ivLogout.setOnClickListener {
                initLogoutDialog()
            }
            btnCreateItem.setOnClickListener {
                showCreateDialog()
            }
            swipeRefreshLayout.setOnRefreshListener {
                getNotes()
            }
        }
    }

     private fun getNotes() {
        homeViewModel.getNotes()
        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
                homeViewModel.notesState.collect { notesResult ->
                    when (notesResult) {
                        is RequestState.Success -> {
                            binding.progressBar.isVisible = false
                            Log.e("Success", notesResult.data.toString()+ notesResult.data.indices)
                            notesList = notesResult.data
                            initRecycler()
                            binding.swipeRefreshLayout.isRefreshing = false
                        }
                        is RequestState.Error -> {
                            binding.progressBar.isVisible = false
                            Log.e("Error", notesResult.exception.toString())
                        }
                        is RequestState.Loading -> {
                            binding.progressBar.isVisible = true
                            Log.e("Loading", "Loading")
                        }
                    }
                }
            }
        }
    }

    private fun initRecycler() {

        val toDoAdapter = ToDoListRecyclerAdapter(
            requireContext(),
            requireActivity(),
            notesList,
            object : OnClickListener {
                override fun onClick(position: Int) {
                    showUpdateDialog(notesList[position])
                }
            })
        binding.rvToDoList.adapter = toDoAdapter

        val swipeGesture = object : SwipeGesture(requireContext()) {
            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                when (direction) {
                    ItemTouchHelper.LEFT -> {
                        notesList[viewHolder.adapterPosition].id?.let { homeViewModel.deleteNote(it) }
                        getNotes()
                    }
                }
            }
        }
        ItemTouchHelper(swipeGesture).attachToRecyclerView(binding.rvToDoList)

        //это я добавил редактирование по свайпу вправо
        val swipeGestureRight = object : SwipeGestureRight(requireContext()) {
            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                when (direction) {
                    ItemTouchHelper.RIGHT -> {
                            showUpdateDialog(notesList[viewHolder.adapterPosition])
                        getNotes()
                    }
                }
            }
        }
        ItemTouchHelper(swipeGestureRight).attachToRecyclerView(binding.rvToDoList)
    }

    private fun showCreateDialog() {
        val mDialogView = LayoutInflater.from(context).inflate(R.layout.create_note_dialog, null)
        val mBuilder = AlertDialog.Builder(context).setView(mDialogView).show()

        val createButton = mDialogView.findViewById<AppCompatImageView>(R.id.btnCreate)
        val titleEditText = mDialogView.findViewById<AppCompatEditText>(R.id.etTitle)
        val descriptionEditText = mDialogView.findViewById<AppCompatEditText>(R.id.etDescription)

        createButton.setOnClickListener {
            val title = titleEditText.text.toString()
            val description = descriptionEditText.text.toString()
            val currentDate  = SimpleDateFormat("dd MMM yyyy (E.), HH:mm:ss", Locale.getDefault()).format(Calendar.getInstance().time).toString()
            if (title.isEmpty() || description.isEmpty()) {
                Toast.makeText(context, "Please check the fields", Toast.LENGTH_SHORT).show()
            } else {
                homeViewModel.createNote(Note(auth.uid, title, description, currentDate))
                getNotes()
                mBuilder.dismiss()
            }
        }
    }

    private fun showUpdateDialog(note: Note) {
        val mDialogView = LayoutInflater.from(context).inflate(R.layout.update_note_dialog, null)
        val mBuilder = AlertDialog.Builder(context).setView(mDialogView).show()

        val createButton = mDialogView.findViewById<AppCompatImageView>(R.id.btnUpdate)
        val titleEditText = mDialogView.findViewById<AppCompatEditText>(R.id.etTitle)
        val descriptionEditText = mDialogView.findViewById<AppCompatEditText>(R.id.etDescription)

        titleEditText.setText(
            note.title.toString(),
            TextView.BufferType.EDITABLE
        )
        descriptionEditText.setText(
            note.description.toString(),
            TextView.BufferType.EDITABLE
        )
        createButton.setOnClickListener {
            val title = titleEditText.text.toString()
            val description = descriptionEditText.text.toString()
            if (title.isEmpty() || description.isEmpty()) {
                Toast.makeText(context, "Please check the fields", Toast.LENGTH_SHORT).show()
            } else {
                val updatedNote = Note(note.id, title, description)
                homeViewModel.updateNote(updatedNote)
                getNotes()
                mBuilder.dismiss()
            }
        }
    }

    private fun onBackPressed() {
        val callback = object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                activity?.finish()
            }
        }
        requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, callback)
    }

  }

ToDoListRecyclerAdapter.kt

class ToDoListRecyclerAdapter(
    private val context: Context,
    private val activity: FragmentActivity,
    private val notesList: ArrayList<Note>,
    private val onClickListener: OnClickListener
) : ListAdapter<Note, ToDoListRecyclerAdapter.ViewHolder>(DiffCallback()) {

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val binding = ItemHomeBinding.bind(itemView)
        fun bind(note: Note) {
            with(binding) {
                tvTitle.text = note.title
                tvDescription.text = note.description
                tvData.text = note.date
                clItem.setOnClickListener {
                    onClickListener.onClick(adapterPosition)
                }
             }
        }
      
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_home, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(notesList[position])
    }

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

class DiffCallback : DiffUtil.ItemCallback<Note>() {
    override fun areItemsTheSame(oldItem: Note, newItem: Note): Boolean {
        return oldItem.title == newItem.title
    }

    override fun areContentsTheSame(oldItem: Note, newItem: Note): Boolean {
        return oldItem == newItem
    }
}

Заранее благодарен за помощь!)


Ответы (0 шт):