При добавлении записи в 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
}
}
Заранее благодарен за помощь!)