I have a RecyclerView which was build using an Arraylist. That Arraylist consists of User defined objects named ListItem.
Each recyclerview has a card view. Each CardView holds each ListItem.
I have removed one CardView from that RecyclerView.
When I rotate the screen , A new Activity is created which results in showing the old data. But I want the recyclerview to hold only updated list and should retain the scrolled position.
ListItem class :
class ListItem(var title: String, var info: String, val imageResource: Int) {
}
MainActivity class :
class MainActivity : AppCompatActivity() {
private lateinit var mSportsData: ArrayList<ListItem>
private lateinit var mAdapter: MyAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val gridColumnCount = resources.getInteger(R.integer.grid_column_count)
recycler_view.layoutManager = GridLayoutManager(this,gridColumnCount)
mSportsData = ArrayList()
recycler_view.setHasFixedSize(true)
initializeData()
recycler_view.adapter = mAdapter
var swipeDirs = 0
if (gridColumnCount <= 1) {
swipeDirs = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
}
val helper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN,swipeDirs) {
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
val from = viewHolder.adapterPosition
val to = target.adapterPosition
Collections.swap(mSportsData,from,to)
mAdapter.notifyItemMoved(from,to)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
mSportsData.removeAt(viewHolder.adapterPosition)
mAdapter.notifyItemRemoved(viewHolder.adapterPosition)
}
})
helper.attachToRecyclerView(recycler_view)
}
private fun initializeData() {
val sportsList : Array<String> = resources.getStringArray(R.array.sports_titles)
Log.d("Printing","$sportsList")
val sportsInfo : Array<String> = resources.getStringArray(R.array.sports_info)
val sportsImageResources : TypedArray = resources.obtainTypedArray(R.array.sports_images)
mSportsData.clear()
for (i in sportsList.indices-1) {
Log.d("Printing","${sportsList[i]},${sportsInfo[i]},${sportsImageResources.getResourceId(i,0)}")
mSportsData.add(ListItem(sportsList[i], sportsInfo[i], sportsImageResources.getResourceId(i, 0)))
}
sportsImageResources.recycle()
mAdapter = MyAdapter(mSportsData,this)
mAdapter.notifyDataSetChanged()
}
fun resetSports(view: View) {
initializeData()
}
}
MyAdapter class :
class MyAdapter(var mSportsData: ArrayList<ListItem>, var context: Context) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(context).inflate(R.layout.wordlist_item,parent,false))
}
override fun getItemCount() = mSportsData.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val listItem = mSportsData.get(position)
holder.bindTo(listItem)
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
init {
itemView.setOnClickListener(this)
}
override fun onClick(view: View) {
val currentSport = mSportsData.get(adapterPosition)
val detailIntent = Intent(context, DetailActivity::class.java)
detailIntent.putExtra("title", currentSport.title)
detailIntent.putExtra("image_resource", currentSport.imageResource)
context.startActivity(detailIntent)
}
fun bindTo(currentSport : ListItem){
itemView.heading_textview.setText(currentSport.title)
itemView.description_textview.setText(currentSport.info)
Glide.with(context).load(currentSport.imageResource).into(itemView.image_view)
}
}
}
You can restrict activity restarting in your Manifest if you have same layout for Portrait and Landscape mode.
Add this to your activity in the manifest.
<activity android:name=".activity.YourActivity"
android:label="#string/app_name"
android:configChanges="orientation|screenSize"/>
If you don't want to restrict screen orientation changes, then you can use OnSaveInstanceState method to save your older data when orientation changed. Whatever data you save via this method you will receive it in your OnCreate Method in bundle. Here is the helping link. So here as you have ArrayList of your own class type you also need to use Serializable or Parcelable to put your ArrayList in your Bundle.
Except these making ArrayList as public static is always a solution, But its not a good solution in Object Oriented paratime. It can also give you NullPointerException or loss of data, in case of low memory conditions.
It looks like initializeData is called twice since onCreate is called again on orientation change, you could use some boolean to check if data has been already initialized then skip initializing
What you are doing is you are deleting the values that are passed down to the recyclerview but when the orientation changes the recyclerview reloads from activity and the original data from activity is passed down again and nothing changes, so if you want to save the changes in recyclerview you have to change the original data in the activity so that if the view reloads the data is the same.
I think u initialize adapter in oncreate method in which the whole adapter will be recreated and all datas is also newly created when configuration changes. Because u init data in oncreate method. Try something globally maintain the list and also delete the item in the list in activity when u delete in adapter also. Or try something like view model architecture
Use MVVM pattern in the project. It will manage the orientation state.
MVVM RecyclerView example:
https://medium.com/#Varnit/android-data-binding-with-recycler-views-and-mvvm-a-clean-coding-approach-c5eaf3cf3d72
Related
I am getting data from API http and using dataBinding and viewModel, all works but when I try to convert my list to mutableList and add All don't getting nothing, also try pass the data of simple way and working , the data is be there, the problem is that notifyDataSetChanged() don't do changes in my Adapter and I dont see nathing in the recyclerView.
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MostPopularTVShowsViewModel
private lateinit var activityMainBinding : ActivityMainBinding
private var tvShows: List<TVShow> = ArrayList()
private lateinit var tvShowAdapter:TVShowsAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main)
doInitialization()
}
private fun doInitialization(){
activityMainBinding.tvShowRecycleView.setHasFixedSize(true)
viewModel= ViewModelProvider(this).get(MostPopularTVShowsViewModel::class.java)
tvShowAdapter= TVShowsAdapter(tvShows)
activityMainBinding.tvShowRecycleView.adapter=tvShowAdapter
getMostPopularTVShows()
}
private fun getMostPopularTVShows(){
activityMainBinding.isLoading=true
viewModel.getMostPopularTVShows(0).observe(this, { mostPopularTVShowsResponse ->
activityMainBinding.isLoading=false
if (mostPopularTVShowsResponse != null){
tvShows.toMutableList().addAll(mostPopularTVShowsResponse.tvShows)
//tvShows=mostPopularTVShowsResponse.tvShows
println("size is: "+tvShows.size)
tvShowAdapter.notifyDataSetChanged()
}else{
Toast.makeText(this," NULL", Toast.LENGTH_SHORT).show()
}
})
}
}
when i change tvShows=mostPopularTVShowsResponse.tvShows insted tvShows.toMutableList().addAll(mostPopularTVShowsResponse.tvShows) the list gets the data but notifyDataSetChanged dont working
this is my adapter
class TVShowsAdapter(private val items: List<TVShow>): RecyclerView.Adapter<TVShowsAdapter.ViewHolder>(){
private lateinit var layoutInflater: LayoutInflater
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
layoutInflater= LayoutInflater.from(parent.context)
val binding: ItemContainerTvShowBinding = DataBindingUtil.inflate(
layoutInflater, R.layout.item_container_tv_show,parent,false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int)= holder.bind(items[position])
override fun getItemCount()= items.size
class ViewHolder(private val itemContainerTvShowBinding: ItemContainerTvShowBinding):
RecyclerView.ViewHolder(itemContainerTvShowBinding.root){
fun bind (tvShow: TVShow){
itemContainerTvShowBinding.tvShow=tvShow
itemContainerTvShowBinding.executePendingBindings()
}
}
}
You're not actually changing the data in the adapter. You're passing in a reference to the tvShows ArrayList when you create the adapter, so if you changed the contents of that list the adapter would be able to see it. But when you do
tvShows.toMutableList().addAll(mostPopularTVShowsResponse.tvShows)
you're creating a new, separate list by calling toMutableList, and you're adding stuff to that. tvShows is still the original, immutable ArrayList with nothing in it.
If you're going to do it this way, you need to make the list mutable from the beginning
val tvShows = mutableListOf<TVShow>()
then you can clear and add to it when you get new data.
Generally though, a better idea is to give the adapter some kind of setData function where you pass in a list, so it can update its own internal data set and notify itself about the change. That way the adapter manages it state itself, all your activity or fragment needs to do is pass it some new data
I am using recyclerView to show list of available apps in device..moreover I am using bottomSheet to show more details about selected app ...in this section, I place uninstall button ...here I use uninstall code and from onActivityResult method in BottomSheetDialog.kt file ... on OK pressed ....I want to delete that app/item from list and update View....here list is correct in coding but recyclerView doesn't update its list
Note: I debug the code and found that list got updated in BottomSheet File...I comment out that ....but
recyclerView doesn't
I searched on internet, but didn't find solution which fits in my case
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView.adapter = Adapter(applicationList) // here I send mutable list of all apps in device to adapter
recyclerView.layoutManager = LinearLayoutManager(this)
private fun getApps(List: MutableList<ResolveInfo>): MutableList<AppData> {
// here I return list to adapter with details of installed apps like icon, name, packageName etc
}
DataClass
data class AppData(
val icon: Drawable,
val name: String,
val packageName: String
.....
.....)
Adapter.kt
class Adapter(private val listOfApps: MutableList<AppData>) :
RecyclerView.Adapter<Adapter.ViewHolder>() {
// here I receive mutableList in constructor of Adapter
class ViewHolder(appView: View) : RecyclerView.ViewHolder(appView), View.OnClickListener,
View.OnLongClickListener {
init { // initiate both click listeners
appView.setOnClickListener(this)
appView.setOnLongClickListener(this)
}
// call elements from activity.xml
val icon: ImageView = appView.App_icon
val name: TextView = appView.App_name
val size: TextView = appView.App_size
override fun onClick(v: View?) {
Toast.makeText(v?.context, "OnClick", Toast.LENGTH_SHORT).show()
}
override fun onLongClick(v: View?): Boolean {
val bottomSheetDialog = BottomSheetDialog(currentItem, appList)
// send currentItem and all List to BottomSheetDialog to show details with the help of function
// Show bottomSheet on LongPress
return true
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder // done
override fun getItemCount() = listOfApps.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val currentItem = listOfApps[position]
holder.icon.setImageDrawable(currentItem.icon)
holder.name.text = currentItem.name
holder.size.text = currentItem.size
}
BottomSheetDialog.kt ...... here in onActivtyResult I delete item and call notify method ... problem is here
class BottomSheetDialog(private val appData: AppData, private val appList: MutableList<AppData>) :
BottomSheetDialogFragment() {
// here I receive appData and AppList in constructor from Adapter OnLongPress
override fun onCreateView() // done
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// here when bottomSheet popup and on click of uninstall.....I check whether user click on OK or CANCEL in onActivity Method (overidden below)
Uninstall_App.setOnClickListener {
// permission in manifest added
val intent = Intent(Intent.ACTION_DELETE)
intent.data = Uri.parse("package:${appData.packageName}")
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true)
startActivityForResult(intent, 1)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// get result from uninstall dialog
if (resultCode == -1) { // ok pressed
Toast.makeText(context, "ok clicked", Toast.LENGTH_SHORT).show()
dismiss()
// here when user pressed OK....delete that item from List
val index = appList.indexOf(appData)
appList.removeAt(index)
Adapter(appList).notifyItemRemoved(index)
Adapter(appList).notifyDataSetChanged()
// I check above three line by debugging it
// 1. val index .. return index of current item
// 2. this line remove that item
// 3. Adapter(appList) .... notify Item removed
// 4. here that indexed item is removed but view is not updated
// Note: if it is wrong which is the best method to do this
} else if (resultCode == 0) { // cancel pressed
Toast.makeText(context, "Cancel Click", Toast.LENGTH_SHORT).show()
}
}
these lines
Adapter(appList).notifyItemRemoved(index)
Adapter(appList).notifyDataSetChanged()
are both creating new adapters, notify them and.. thats all. they aren't attached to any RecyclerView (as you do in onCreate), so won't be drawn anywhere
you should notify adapter already set for RecyclerView - keep reference in Activity and refer to it instead of creating new one
What you did here is created two new adapters (that have no relation to the adapter used by recycler view except the type of adapter is the same):
Adapter(appList).notifyItemRemoved(index)
Adapter(appList).notifyDataSetChanged()
You can create an interface to listen for changes from BottomSheetDialog:
interface OnAppDeletedListener {
fun appDeletedAtIndex(index: Int)
}
Update your BottomSheetDialog to accept an additional argument of type OnAppDeletedListener:
class BottomSheetDialog(private val appData: AppData, private val appList: MutableList<AppData>, private val listener: OnAppDeletedListener) :
BottomSheetDialogFragment() {
...
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
val index = appList.indexOf(appData)
listener.appDeletedAtIndex(index)
dismiss()
}
}
}
Update your adapter. It must not be responsible for showing any dialogues. Activity or Fragment is responsible for that.
class Adapter(private val listOfApps: MutableList<AppData>, private val longClickListener: View.OnLongClickListener) :
RecyclerView.Adapter<Adapter.ViewHolder>() {
// here I receive mutableList in constructor of Adapter
class ViewHolder(appView: View) : RecyclerView.ViewHolder(appView), View.OnClickListener {
init { // initiate both click listeners
appView.setOnClickListener(this)
appView.setOnLongClickListener(longClickListener)
}
// call elements from activity.xml
val icon: ImageView = appView.App_icon
val name: TextView = appView.App_name
val size: TextView = appView.App_size
override fun onClick(v: View?) {
Toast.makeText(v?.context, "OnClick", Toast.LENGTH_SHORT).show()
}
}
}
And update your activity code:
class MainActivity : AppCompatActivity() {
private lateinit var adapter: Adapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val longClickListener = object: View.OnLongClickListener {
override fun onLongClick(v: View?): Boolean {
displayAppInfoDialog()
return true
}
}
adapter = Adapter(applicationList)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)
}
private fun displayAppInfoDialog() {
val listener = object: OnAppDeletedListener() {
fun appDeletedAtIndex(index: Int) {
adapter.notifyItemRemoved(index)
}
}
val bottomSheetDialog = BottomSheetDialog(currentItem, appList, listener)
bottomSheetDialog.show()
}
...
}
As already stated, you are not updating the existing Adapter, you are instead creating two new instances.
Replace this line:
recyclerView.adapter = Adapter(applicationList) // here I send mutable list of all apps in device to adapter
With
this.adapter = Adapter(applicationList)
recyclerView.adapter = this.adapter
Also add val adapter: Adapter? to your class.
Now you have a reference to the adapter the RecyclerView has.
Finally, when you want to "update" it:
// here when user pressed OK....delete that item from List
val index = appList.indexOf(appData)
appList.removeAt(index)
Adapter(appList).notifyItemRemoved(index)
Adapter(appList).notifyDataSetChanged()
Should become...
// here when user pressed OK....delete that item from List
val index = appList.indexOf(appData)
appList.removeAt(index)
this.adapter.notifyItemRemoved(index)
this.adapter.notifyDataSetChanged()
IMPORTANT CAVEAT: There are other issues here with the separation of concerns in your code, but among them, the fact that the appList you use here, is a local list; does it contain the items from applicationList (the one you used when you created the adapter)? If it doesn't then you need to expose said list so you can either modify it/replace it, etc.
The Adapter does NOT manage the list for you, it merely uses it to adapt each item to a ViewHolder. If you modify the list the adapter has, and you tell it that you inserted an item at certain position, etc. All the adapter does is (a lot behind the scenes) and "re-binds" the view at that position (if it's visible) with the new data.
I'm new in Android dev.
In my code i don't using onClick method, but i using setOnClickListener and Callback. The main problem that is in this way i don't know how to get the position of the item in RecyclerView.
Here is my Adapter:
class TestAdapter(val test : ArrayList<Test>, private val testAdapterCallback: (Test, Int)->Unit) : RecyclerView.Adapter<TestAdapter.ViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.test_view_item, parent, false)
return ViewHolder(v)
}
override fun getItemCount(): Int {
return test.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val num : Test = test[position]
holder.textView.text = num.id.toString()
holder.cardView.setTag(position)
holder.cardView.setOnClickListener(){
testAdapterCallback(num)
}
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
val cardView = itemView.findViewById<CardView>(R.id.testCardView)
val textView = itemView.findViewById<TextView>(R.id.testTextView)
}
}
I have added second parametr into callback but i don't know how i must change my adapter's inicializations in this peace of code:
val adapter = TestAdapter(list) { item ->
testAdapterItemClick(item)
}
In activity i'm using this method :
private fun testAdapterItemClick(item: Test) {}
Please, help me to check the position of the choosen element. I need it later.
Thanks in advance)
P.S. Sorry for my English
Add the position as parameter in the callback.
So, instead of: private val testAdapterCallback: (Test)->Unit
Use: private val testAdapterCallback: (Test, Int)->Unit.
This way you can pass the position in the callback.
holder.cardView.setOnClickListener(){
testAdapterCallback(num, position)
}
In your activity:
val adapter = TestAdapter(list) { item, position ->
testAdapterItemClick(item)
}
Create interface for your OnClickListener
interface OnClickListener{
fun clickItem(test: Test, index: Int)
}
Pass listener to your adapter like below.
class TestAdapter(
var test : ArrayList<Test>?,
val clickListener: OnClickListener,
var mActivity: Activity
) :
RecyclerView.Adapter<TestAdapter.MyViewHolder>() {
}
Now in your onBindViewHolder add click listener.
var mtest= test !!.get(i)
holder.cardView.setOnClickListener {
clickListener.clickItem(mtest, i)
}
Implement Listener to your activity and initialize it.
this.mOnClickListener = this
Pass listener to your adapter where you passing the arraylist.
mTestAdapter = TestAdapter(arrayList, mOnClickListener ,mActivity)
You'll get the position in your activity override method.
override fun editItem(mTest: Test, index: Int) {
if (mTest!= null) {
}
}
I user MVVM and RecyclerView in this app so the recycle view show the list perfectly but when i add the view model to adapter i get an error in the logcat
Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.
i am new in this MVVM and i know is this possible or is any other way to do this
this is my adapter class with the viewHolder
class KeefAdapter : RecyclerView.Adapter<KeefViewHolder>() {
var dataOfAllKeef = listOf<String>()
init {
dataOfAllKeef = arrayListOf("Marijuwana" , "Bango" , "Weed" , "Hash")
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): KeefViewHolder {
lateinit var binding: KeefSingleItemBinding
binding = DataBindingUtil.inflate(LayoutInflater.from(parent.context) , R.layout.keef_single_item , parent , false)
val viewModel:OrderYourKeefViewModel = ViewModelProvider(OrderYourKeef()).get(OrderYourKeefViewModel::class.java)
binding.orderViewModelWithSingle = viewModel
viewModel.count.observe(OrderYourKeef(), Observer { newCountOfHash->
binding.root.theCountOfHash.text = newCountOfHash.toString()
})
return KeefViewHolder(binding.root)
}
override fun getItemCount() = dataOfAllKeef.size
override fun onBindViewHolder(holder: KeefViewHolder, position: Int) {
val item = dataOfAllKeef[position]
holder.keefName.text = item
if (item.equals("Marijuwana")) {
holder.keefImage.setImageResource(R.mipmap.marijuana)
} else if (item.equals("Bango")) {
holder.keefImage.setImageResource(R.mipmap.bango)
} else if (item.equals("Weed")) {
holder.keefImage.setImageResource(R.mipmap.weed)
} else if (item.equals("Hash")) {
holder.keefImage.setImageResource(R.mipmap.hashesh)
}
}
}
class KeefViewHolder(itemView:View) : RecyclerView.ViewHolder(itemView) {
var keefName:TextView = itemView.keefName
var keefImage: ImageView = itemView.keefImage
var increase: Button = itemView.increaseTheCount
var decrease: Button = itemView.minusTheCount
var theCountOfKeef: TextView = itemView.theCountOfHash
}
I think this is not the correct way to implement the MVVM pattern.
You have to call the viewModel = ViewModelProviders in your Activity. And after fetching the list items, pass it to your adapter and call the notifyDataSetChanged():
updateListItems(newListItems: List<YourItem>) {
currentItems = newListItems
notifyDataSetChanged()
}
Read more about it here
Adapter seems to be designed to be used rather passively than actively.
In OP's code, he would observe and get newCountOfHash in onCreateViewHolder to set it to binding.root.theCountOfHash.text. So this is a case that Adapter would actively seek and grab a value.
To avoid this 'active' Adapter, we should define Adapter behaving passively. Locally define countOfHash as Adapter's field value. The Adapter shouldn't mind countOfHash is LiveData or not. It just looks the field value.
class KeefAdapter : RecyclerView.Adapter<KeefViewHolder>() {
var countOfHash
override fun onBindViewHolder(holder: KeefViewHolder, position: Int) {
// You should not do this in onCreateViewHolder
// because that is done only once on creation time.
// (not invoked later again)
binding.root.theCountOfHash.text = countOfHash
}
}
Then outside of the Adapter, from Activity or Fragment that holds the Adapter, you may update Adapter.countOfHash with an Observer:
val viewModel:OrderYourKeefViewModel
= ViewModelProvider(OrderYourKeef()).get(OrderYourKeefViewModel::class.java)
viewModel.count.observe(OrderYourKeef(), Observer { newCountOfHash ->
Adapter.countOfHash = newCountOfHash.toString()
})
(Note: I'm not using Kotlin actively, there may be some syntax mistakes)
I'm having a problem when call the notifyItemRangeInserted of the adapter. When I call this method, nothing happens, simple as that. I've tried to set some println() in the ViewHolderAdapter, but he isn't called, so I can't view the prints.
I've tried all of the "notify" commands of the adapter, and none of these work. Simply nothing happens.
That's my MainActivity. All the objects and arrays I've tested, all of them are working like a charm. I can't understand why the notify doesn't work.
class MainActivity:AppCompatActivity(){
//Declarations of the variables
var pageNumber = 1
var limitPerPage = 5
lateinit var product: Product
var productList = ArrayList<EachProduct>()
var myAdapter =ViewHolderAdapter(productList, productList.size)
override fun onCreate(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView.layoutManager = LinearLayoutManager(this#MainActivity)
recyclerView.adapter = myAdapter
The code to add items on the list and notify the ViewHolderAdapter is
//update the product list
fun updateProductList(product:Product){
for(i in 0 until 5 step 1){
productList.add(product.produtos[i])
}
showData(productList,pageNumber*limitPerPage)//then notify
}
fun showData(productList:List<EachProduct>,productsListSize:Int){
myAdapter.notifyItemRangeInserted(0,productList.size)
}
That's my ViewHolderAdapter class
class ViewHolderAdapter(private var products: List<EachProduct>, private val productsListSize: Int): RecyclerView.Adapter<ViewHolderAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent:ViewGroup,viewType:Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_layout, parent, false)
returnViewHolder(view)
}
override fun getItemCount() = productsListSize
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.productName.text=products[position].nome
Picasso.get().load(products[position].fabricante.img).into((holder.productLogo))
}
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
val productName:TextView=itemView.ProductName
var productLogo:ImageView=itemView.ProductLogo
}
}
I expect the ViewHolderAdapter to be called, but this is not occurring. Why is that happens? I can't understand. I'll be very grateful if someone could help me.
Because initial value of the variable productsListSize is zero. Remove it from the constructor and change adapter like this:
class ViewHolderAdapter(private var products: List<EachProduct>): RecyclerView.Adapter<ViewHolderAdapter.ViewHolder>() {
override fun getItemCount() = products.size
}
A reason can be that the initial size of the item list you want to show is 0 and the recycler view height is set to wrap content. At the moment, for this case I see 2 options:
Keep wrap content for recycler view and make sure the initial list size > 0.
Set the height of the recycler view to match_parent or a fixed size and notifyItemRangeInserted will work without issues.