I am fetching the categories from an API and I would like to fire up a new fragment by passing the category name to retrofit on the button click. I am thinking of doing it in my UI with getText() on the button clicked and firing up the API call which will display the result on a new fragment.
The API I am using is https://fakestoreapi.com/
To my understanding, I have to handle the click events in the UI part (Fragment's Code).
The code below is in my FakeApiService.kt
@GET("categories")
suspend fun getCategories(): List<String>
@GET("categories/{product}")
suspend fun getProduct(@Path(value = "product", encoded = true) productType: String): List<Product>
However, I am having trouble adding a clickListenerto the the buttons.
Here is the code for recycleView adapter
class MyCategoryRecyclerViewAdapter(
private val values: ArrayList<String>
) : RecyclerView.Adapter<MyCategoryRecyclerViewAdapter.MyCategoryRecyclerViewHolder>() {
inner class MyCategoryRecyclerViewHolder :
RecyclerView.ViewHolder(binding.root) {
fun bind(category: String) {
binding.category = category
binding.btnCategoryName.setOnClickListener {
Log.d("Debug On", "Button clicked ${binding.btnCategoryName.text}")
}
}
}
private lateinit var binding: CategoryItemBinding
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): MyCategoryRecyclerViewHolder {
binding = CategoryItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return MyCategoryRecyclerViewHolder()
}
override fun onBindViewHolder(holder: MyCategoryRecyclerViewHolder, position: Int) {
holder.bind(values[position])
}
fun updateData(values: ArrayList<String>) {
this.values.clear()
this.values.addAll(values)
}
override fun getItemCount() = values.size
}
My ViewModel for the categories fragment.
enum class FakeApiStatus { LOADING, ERROR, DONE }
class CategoryViewModel : ViewModel() {
// The internal MutableLiveData that stores the status of the most recent request
private val _status = MutableLiveData<FakeApiStatus>()
val status: LiveData<FakeApiStatus> = _status
val categories: ArrayList<String> = ArrayList()
/**
* Call getCategories() on init so we can display status immediately.
*/
init {
Log.d("Debug", "view model created")
getCategories()
}
private fun getCategories() {
viewModelScope.launch(Dispatchers.IO) {
_status.postValue(FakeApiStatus.LOADING)
try {
categories.clear()
categories.addAll(FakeApi.retrofitService.getCategories())
_status.postValue(FakeApiStatus.DONE)
} catch (e: Exception) {
_status.postValue(FakeApiStatus.ERROR)
}
}
}
}
Code for the fragment.
class CategoryFragment : Fragment() {
private lateinit var binding: FragmentCategoryBinding
private val adapter = MyCategoryRecyclerViewAdapter(ArrayList())
private val viewModel: CategoryViewModel by lazy {
ViewModelProvider(this)[CategoryViewModel::class.java]
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentCategoryBinding.inflate(inflater)
binding.rvCategoryList.adapter = adapter
viewModel.status.observe(viewLifecycleOwner) {
when (it) {
FakeApiStatus.DONE -> binding.animationRotation.visibility = View.GONE
FakeApiStatus.ERROR -> Toast.makeText(
context,
"No Internet!",
Toast.LENGTH_LONG
).show()
else -> {}
}
observeCategories()
}
return binding.root
}
private fun observeCategories(){
adapter.updateData(viewModel.categories)
adapter.notifyDataSetChanged()
}
}
This is the layout for my item
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="category"
type="String" />
</data>
<Button
android:id="@+id/btn_category_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{category.toUpperCase()}"
tools:text="Test"
android:onClick="TODO"
android:layout_margin="@dimen/cardview_default_elevation"
android:textAppearance="?attr/textAppearanceListItem" />
</layout>
And the layout for Fragment(RecycleView)
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_category_list"
android:name="com.example.task.categories.CategoryFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:context=".categories.CategoryFragment"
tools:listitem="@layout/category_item" />
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/animation_rotation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>