Search code examples
androidandroid-recyclerviewandroid-adapter

Unresolved reference: adapter in RecyclerviewFragment


I'm currently trying to implement editing items in Recyclerview on imageView click in a single Recyclerview row, but I can't figure out how to solve the reference for adapter outside of onCreateView in a fragment. How do I fix this issue and get rid of the error? What is the cause of this problem?

RecyclerviewFragment.kt:

class RecyclerviewFragment : Fragment() {

    private lateinit var mUserViewModel: UserViewModel
    private lateinit var viewHolder: ViewHolder

    private var _binding: FragmentRecyclerviewBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View {
        _binding = FragmentRecyclerviewBinding.inflate(inflater, container, false)
        mUserViewModel = ViewModelProvider(this)[UserViewModel::class.java]

        val adapter = ListAdapter{showUpdateDialog()}
        val recyclerView = binding.recyclerView
        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(requireContext())

        // Creates a controller responsible for swiping and moving the views in recyclerview
        val itemTouchController = ItemTouchHelper(
            object : ItemTouchHelper.SimpleCallback(
                ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.LEFT
            ) {
                override fun onMove(
                    recyclerView: RecyclerView,
                    viewHolder: ViewHolder, target: ViewHolder,
                ): Boolean {
                    // Move specific item from "fromPos" to "toPos" in recyclerview adapter
                    val fromPos = viewHolder.bindingAdapterPosition
                    val toPos = target.bindingAdapterPosition
                    adapter.notifyItemMoved(fromPos, toPos)
                    return true // true if moved, false otherwise

                }

                override fun onSwiped(viewHolder: ViewHolder, direction: Int) {
                    mUserViewModel.deleteUser(adapter.getTaskPosition(viewHolder.bindingAdapterPosition))
                    Toast.makeText(context, "Task deleted", Toast.LENGTH_SHORT).show()
                    adapter.notifyItemRemoved(viewHolder.bindingAdapterPosition)
                }
            })

        itemTouchController.attachToRecyclerView(binding.recyclerView)

        mUserViewModel.readAllData.observe(viewLifecycleOwner) { user ->
            adapter.setData(user)
        }
        return binding.root
    }

    private fun updateItemInDatabase(dialog: DialogInterface) {
        val editText = (dialog as AlertDialog).findViewById<EditText>(R.id.editTextDialog)
        val task = editText?.text.toString()

        if(inputCheck(task)) {
            // Update an entity
            mUserViewModel.updateUser(adapter.getTaskPosition(viewHolder.bindingAdapterPosition))
            Toast.makeText(context, "Task updated", Toast.LENGTH_SHORT).show()
        }
        else {
            Toast.makeText(context, "Please fill out required fields", Toast.LENGTH_SHORT).show()
        }
    }

    private fun inputCheck(task: String): Boolean {
        return !(TextUtils.isEmpty(task))
    }

    private fun showUpdateDialog() {
            MaterialAlertDialogBuilder(requireContext())
                .setView(R.layout.fragment_add)
                .setNegativeButton(getString(R.string.cancel)) { _, _ ->
                    // Respond to negative button press
                    Toast.makeText(context, getString(R.string.cancelled), Toast.LENGTH_SHORT).show()
                }
                .setPositiveButton(getString(R.string.ok)) { dialogInterface, _ ->
                    // Respond to positive button press
                    updateItemInDatabase(dialogInterface)
                }
                .show()
    }
}

Solution

  • Do you require a global reference to your adapter? Where exactly do you want to use the adapter? If thats the case then declare your adapter above onCreateView as

    private lateinit var adapter
    

    then on your onCreateView initialise the adapter as

    adapter = ListAdapter{showUpdateDialog()}
    

    You can then use the adapter reference anywhere you want on that class