I'm working on an Android app that lets you add consoles and games, serving as a library for games, that must be finished before Friday and after adding a new console, or even before, the Recyclerview in activity_dashboard_admin.xml shows the cardview and the delete icon but not element from the database in Firebase. If I click on any delete icon, nothing is removed from the Firebase database.
The debug console shows this error: E/RecyclerView: No adapter attached; skipping layout
I don't know what else to do and it's giving me headache. I'll be eternally grateful to whoever can identify the problem.
Link to the Kotlin classes in the repository: here.
Link to the layouts: here.
EDIT: I managed to solve the problem but the delete button isn't working for some reason.
CodePudding user response:
I have made some changes to the way you have made the adapter
First I have made some changes to the adapter:
// we nee to pass the elements we want to show
class ConsoleAdapter(private val consoles: List<Console>, val itemClickListener: ItemClickListener): RecyclerView.Adapter<ConsoleAdapter.ViewHolder>() {
private lateinit var context: Context
inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
private val binding = RowConsoleBinding.bind(itemView)
fun bind(console: Console) {
val console = console
val id = console.id
val consoleName = console.console
val timestamp = console.timestamp
// Set data
binding.tvConsoleTitle.text = consoleName
// Handle click to delete a console
binding.btnDeleteConsole.setOnClickListener {
itemClickListener.onClickItem(console)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
context = parent.context
return ViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.row_console, parent, false)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(consoles[position])
}
override fun getItemCount(): Int = consoles.size
interface ItemClickListener{
fun onClickItem(console: Console)
}
}
I have removed all logic, this will be moved to the activity. Furthermore, I have added an ItemClickListener
, which we implement in the activity, this ItemClickListener
will remove the item from Firebase and the view.
Next, we made some changes to the activity: First, implement the interface of the adapter:
class DashboardAdminActivity : AppCompatActivity(), ItemClickListener {
...
second, no need to lateinit those var
's
// Arraylist for the categories
private var consoles = arrayListOf<Console>()
// make a array for a copy
private var copyList = consoles.clone() as ArrayList<Console>
// Adapter
private var mAdapter = ConsoleAdapter(consoles, this)
Next init Firebase and the UI:
// Init Firebase Auth
firebaseAuth = FirebaseAuth.getInstance()
setUpRecyclerView() // changed
checkUser()
loadConsoles() // changed
...
// setup the RecyclerView
private fun setUpRecyclerView() {
binding.rvConsoles.layoutManager = LinearLayoutManager(applicationContext, RecyclerView.VERTICAL, false)
binding.rvConsoles.adapter = mAdapter
}
...
private fun loadConsoles() { // To get the console list from the db
// Get categories from the db: root > consoles
val aux = FirebaseDatabase.getInstance().getReference("Consoles")
aux.addValueEventListener(object: ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
// Clear list before start adding data into it
consoles.clear()
for(ds in snapshot.children) {
val consoleModel = ds.getValue(Console::class.java)
// Add to arraylist
consoles.add(consoleModel!!)
copyList = consoles.clone() as ArrayList<Console> // make a copy for search
mAdapter.notifyDataSetChanged();
}
}
override fun onCancelled(error: DatabaseError) {
TODO("Not yet implemented")
}
})
}
Last override the onClickItem
from the ConsoleAdapter
override fun onClickItem(console: Console) {
// here we make add the logic to remove item
val builder = AlertDialog.Builder(this@DashboardAdminActivity)
builder.setTitle("Delete").setMessage("Are you sure?")
.setPositiveButton("Confirm") { a, d->
Toast.makeText(applicationContext, "Deleting...", Toast.LENGTH_SHORT).show()
deleteConsole(console)
}
.setNegativeButton("Cancel") { a, d->
a.dismiss()
}
.show()
}
private fun deleteConsole(console: Console) {
// Get the id of the item that will be deleted: root > consoles > id
val id = console.id
val aux = FirebaseDatabase.getInstance().getReference("Consoles")
aux.child("id").removeValue().addOnSuccessListener {
Toast.makeText(applicationContext, "The console was successfully deleted", Toast.LENGTH_SHORT).show()
// **update the UI**
consoles.remove(console)
mAdapter.notifyDataSetChanged()
}
.addOnFailureListener { e->
Toast.makeText(applicationContext, "Error while deleting: ${e.message}", Toast.LENGTH_SHORT).show()
}
}
Change the search:
This will eleminate the ConsoleFilter.kt
and FilterConsole.kt
files.
// Search function
binding.etSearchConsole.doOnTextChanged { text, _, _, _ ->
val filteredList = arrayListOf<Console>()
consoles.clear()
if (!text.isNullOrBlank()) {
val filterPattern = text.toString().lowercase(Locale.getDefault())
for (item in copyList) {
if (item.console.lowercase(Locale.getDefault()).contains(filterPattern)) {
filteredList.add(item)
}
}
consoles.addAll(filteredList)
} else {
consoles.addAll(copyList)
}
mAdapter.notifyDataSetChanged()
}
I have created a pull request on your project. I hope it will help you out.