Android SDK
02 / 03

UI: Views, RecyclerView & Fragments

Android SDK: UI Views, RecyclerView & Fragments

View Binding

// build.gradle: viewBinding { enabled = true }

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.textView.text = "Hello"
        binding.button.setOnClickListener {
            binding.textView.text = "Clicked!"
        }
    }
}

// In Fragments
class MyFragment : Fragment(R.layout.fragment_my) {
    private var _binding: FragmentMyBinding? = null
    private val binding get() = _binding!!

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        _binding = FragmentMyBinding.bind(view)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null   // avoid memory leak
    }
}

RecyclerView

// Adapter
class ItemAdapter(
    private val items: List<String>,
    private val onItemClick: (String) -> Unit
) : RecyclerView.Adapter<ItemAdapter.ViewHolder>() {

    inner class ViewHolder(val binding: ItemRowBinding) :
        RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemRowBinding.inflate(
            LayoutInflater.from(parent.context), parent, false
        )
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = items[position]
        holder.binding.textView.text = item
        holder.binding.root.setOnClickListener { onItemClick(item) }
    }

    override fun getItemCount() = items.size
}

// In Activity/Fragment
binding.recyclerView.apply {
    layoutManager = LinearLayoutManager(context)
    adapter = ItemAdapter(listOf("Item 1", "Item 2")) { item ->
        Toast.makeText(context, item, Toast.LENGTH_SHORT).show()
    }
}

// DiffUtil for efficient updates
class ItemDiffCallback(
    private val oldList: List<String>,
    private val newList: List<String>
) : DiffUtil.Callback() {
    override fun getOldListSize() = oldList.size
    override fun getNewListSize() = newList.size
    override fun areItemsTheSame(old: Int, new: Int) = oldList[old] == newList[new]
    override fun areContentsTheSame(old: Int, new: Int) = oldList[old] == newList[new]
}

Fragments

// Fragment definition
class DetailFragment : Fragment(R.layout.fragment_detail) {
    private val args: DetailFragmentArgs by navArgs()  // Navigation Safe Args

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // Access args.itemId, args.title
    }

    companion object {
        fun newInstance(id: Int): DetailFragment {
            return DetailFragment().apply {
                arguments = bundleOf("item_id" to id)
            }
        }
    }
}

// Fragment transactions (without Navigation Component)
supportFragmentManager.commit {
    setReorderingAllowed(true)
    replace(R.id.fragment_container, DetailFragment.newInstance(42))
    addToBackStack(null)
}

// Fragment result API (pass data back to parent fragment)
// Parent fragment:
childFragmentManager.setFragmentResultListener("requestKey", viewLifecycleOwner) { _, bundle ->
    val result = bundle.getString("resultKey")
}

// Child fragment:
parentFragmentManager.setFragmentResult("requestKey",
    bundleOf("resultKey" to "value")
)

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free