I am following Shrine example application which is implemented in Kotlin part of Google official codelabs for developers. The application and codelab
The last step, We are asked to
Modify your Shrine application to change the product images shown when a category is selected from the backdrop menu.
In the ProductGridFragment#onCreateView
I attached a onClick listener on one button to begin with (list of categories, are buttons).
As a test, I just popped an element from the list firstly used in Adapter.
theList = ProductEntry.initProductEntryList(resources)
adapter = StaggeredProductCardRecyclerViewAdapter( theList )
val featured = view.findViewById(R.id.featured) as Button
// set on-click listener
featured.setOnClickListener {
theList.pop(1)
adapter.notifyDataSetChanged()
It is not working. Is there other things to do to refresh the view ? all I see in onCreateView
seems to be just for first creation of the fragment, I mean, when onClick
is produced, it seems to me sufficient to just modify the list and notify adapter on changes.
Do I have to do any thing with view
object ?
Any hints ?
Edit 1:
I assigned a new adapter and it works now, this is very nice; Although I do not feel it is performance efficient, as notify for data changes is not really used as intended
featured.setOnClickListener {
theList = ProductEntry.initProductEntryList(resources, "featured")
this.adapter = StaggeredProductCardRecyclerViewAdapter(
theList )
view.recycler_view.adapter = this.adapter
this.adapter.notifyDataSetChanged()
}
in Java/Kotlin you always pass by value, not a reference. So when you passed the list to the StaggeredProductCardRecyclerViewAdapter( theList )
, you should update the list from Adapter, not the one you passed, so for example:
class StaggeredProductCardRecyclerViewAdapter(private val theList: List) {
private var listOfItems = theList
fun removeItem(position: Int) {
listOfItems = listOfItems.remove(position)
notifyDatasetChanged()
}
}
val featured = view.findViewById(R.id.featured) as Button
// set on-click listener
featured.setOnClickListener {
adapter.removeItem(1)
}
EDIT:
I went to the codebase and you are operating on the immutable list inside the StaggeredProductCardRecyclerViewAdapter
. If you want to filter the items on the list based on "featured" for example, you should do this:
class StaggeredProductCardRecyclerViewAdapter(private val initList: List<ProductEntry>?) : RecyclerView.Adapter<StaggeredProductCardViewHolder>() {
private var productList: List<ProductEntry>? = initList
override fun getItemViewType(position: Int): Int {
return position % 3
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StaggeredProductCardViewHolder {
var layoutId = R.layout.shr_staggered_product_card_first
if (viewType == 1) {
layoutId = R.layout.shr_staggered_product_card_second
} else if (viewType == 2) {
layoutId = R.layout.shr_staggered_product_card_third
}
val layoutView = LayoutInflater.from(parent.context).inflate(layoutId, parent, false)
return StaggeredProductCardViewHolder(layoutView)
}
override fun onBindViewHolder(holder: StaggeredProductCardViewHolder, position: Int) {
if (productList != null && position < productList.size) {
val product = productList[position]
holder.productTitle.text = product.title
holder.productPrice.text = product.price
ImageRequester.setImageFromUrl(holder.productImage, product.url)
}
}
override fun getItemCount(): Int {
return productList?.size ?: 0
}
fun replaceList(items: List<ProductEntry>?) {
productList = items
notifyDatasetChanged()
}
}
And in ProductGridFragment:
...
featured.setOnClickListener {
adapter.replaceList(ProductEntry.initProductEntryList(resources, "featured"))
}