I'm a totally newby using Kotlin and I'm trying to create my first app with a lot of test and error (and have worked till now).
My problem is that I have created a recyclerview that have rows from files in firestore (everything correct), in each row a put a button to delete that file from firestore (works smoothly), but after clicking the button the list is not updated so I still see the file that I just removed...
Let me share with you and please help me identify the error cos I did this with room and the list was refreshing acordingly.
My Fragment:
class SharingFragment : Fragment() {
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val binding: FragmentSharesBinding = DataBindingUtil.inflate(
inflater, R.layout.fragment_shares, container, false)
val application = requireNotNull(this.activity).application
val viewModelFactory = SharingViewModelFactory(application)
val sharingViewModel = ViewModelProvider(this,viewModelFactory).get(
SharingViewModel::class.java)
sharingViewModel.getSharedWithMe().observe(this , Observer { list->
// set the layout manager and the adapter for the recycler view
binding.listaRecyclerView.layoutManager = LinearLayoutManager(application)
binding.listaRecyclerView.adapter = InsuranceAdapter(context!!,list)
})
binding.sharingViewModel = sharingViewModel
val root: View = binding.root
return root
}
}
My ViewModel (SharingViewModel):
class SharingViewModel(
application: Application
) : AndroidViewModel(application)
{
var listReturn: MutableLiveData<List<String>>
init {
listReturn = MutableLiveData(listOf())
}
fun getSharedWithMe() : MutableLiveData<List<String>> {
var auth = Firebase.auth
val storage = Firebase.storage
var storageRef = storage.reference
val databaseRef = storageRef.child("shared/${auth!!.currentUser!!.email}")
var listFile = databaseRef.listAll()
listFile.addOnSuccessListener { (items, prefixes) ->
var list: MutableList<String> = mutableListOf()
items.forEach { item ->
list.add(item.name)
}
listReturn.value = listReturn.value?.plus(list)
}
.addOnFailureListener {
// Uh-oh, an error occurred!
}
//Wait to receive the listall
while(listFile.isComplete==false) {Thread.sleep(1000)}
return listReturn
}
fun deleteSharedWithMe(file: String) {
var auth = Firebase.auth
val storage = Firebase.storage
var storageRef = storage.reference
val fileRef =
storageRef.child("shared/${auth!!.currentUser!!.email}/${file}")
fileRef.delete()
listReturn.value = listReturn.value!!.toMutableList().apply {
remove(file)
}.toList()
}
}
and my adapter:
class InsuranceAdapter(val context : Context,val list : List<String>) : RecyclerView.Adapter<InsuranceAdapter.ViewHolder>() {
// Inner ViewHolder class
class ViewHolder(val binding : SharingListBinding) : RecyclerView.ViewHolder(binding.root){}
// function to inflate the layout for each contact and create a new ViewHolder instance
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
SharingListBinding.inflate(LayoutInflater.from(parent.context),parent,false)
)
}
// function to bind the data to the view elements of the ViewHolder
@RequiresApi(Build.VERSION_CODES.O)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.binding.fileTextview.text = list[position]
// delete button onClickListener to delete the
// file from firestore and notify the
// adapter of the change
holder.binding.deleteButton.setOnClickListener{
val application = requireNotNull(Application())
val sharingViewModel = SharingViewModel(Application())
//TODO borrar de Firebase
sharingViewModel.deleteSharedWithMe(list[position])
// dao.delete(list[position]) //this was working when I was using Room and deleting from the DB was refreshing the list
notifyItemChanged(position)
notifyDataSetChanged()
}
}
override fun getItemCount(): Int {
return list.size
}
}
So, what I have followed is to use the function inside the viewmodel to delete the file, but I have no idea why the list is not refreshing, any ideas?
The reason why the list is not refreshing is that you are creating a new instance of the SharingViewModel
in your InsuranceAdapter class, which is not the same instance that is observed by the SharingFragment
In your fragment:
binding.listaRecyclerView.adapter = InsuranceAdapter(context!!, list, sharingViewModel) // pass the ViewModel instance to the adapter
In your adapter
class InsuranceAdapter(
val context: Context,
val list: List<String>,
val viewModel: SharingViewModel // pass the ViewModel instance from the Fragment
)
viewModel.deleteSharedWithMe(list[position]) // use the existing ViewModel instance