Home > Net >  Problems with a Kotlin Android app connected to Firebase due to the Recyclerview
Problems with a Kotlin Android app connected to Firebase due to the Recyclerview

Time:06-30

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.

  • Related