Recyclerview not call onCreateViewHolder
Your getItemCount
method returns 0
. So RecyclerView
never tries to instantiate a view. Make it return something greater than 0
.
for example
@Override
public int getItemCount() {
return data.size();
}
How does the recyclerview adapter know to call onCreateViewHolder?
Whenever the Adapter needs to provide a new view for the RecyclerView to draw, it checks if it has an unused ViewHolder in its pool. If it doesn't, it calls onCreateViewHolder()
so it can create one. Then it calls onBindViewHolder()
for the ViewHolder that came from either source so the contained view can be prepared before being added to the layout.
If you call one of the notify
methods, that triggers it to refresh whichever item rows are affected. It will return any removed rows to the ViewHolder pool and then follow the above steps to get the views it needs for new rows. If you use a notify...changed
method, it will only need to use onBindViewHolder()
for the applicable rows. When you use the nuclear option notifyDataSetChanged()
, it returns all items to the pool.
When the RecyclerView is first displayed, or when the layout is resized, those actions will possibly trigger the need to show more rows. When you scroll the list, items that scroll off the screen are returned to the ViewHolder pool, and when new items scroll into view, ViewHolders need to be created or acquired from the pool as explained above.
By the way, this is going to look ugly because it refreshes the whole list even though only some items are removed:
items.removeAll { item ->
item.checked
}
notifyDataSetChanged()
I recommend this instead so you get a nice transition:
for (i in items.indices.reversed()) {
if (items[i].checked) {
items.removeAt(i)
notifyItemRemoved(i)
}
}
I iterate in reverse so the indices that are removed are stable as you iterate and remove items.
RecyclerView onCreateViewHolder and onBindViewHolder not getting called
The issue was that in the recycler view (activity_travel_view_list.xml) the height and width were set to 0dp. I changed it to android:layout_width="match_parent" & android:layout_height="match_parent" and it worked. Thank you all for your contributions.
Recycler adapter doesn't call onCreateViewHolder
The problem was in root layout of activity. It was android.support.constraint.ConstraintLayout. In combination with parameter layout_height"match_parent" of container of fragment it's give that problem. If change ConstraintLayout to any other - it will work properly.
onCreateViewHolder() of child recycler view not being called in Android [Kotlin]
The problem is that each "floor" (row in the floor RecyclerView) has its own unique "room" RecyclerView, but you never attach an adapter to those room RecyclerViews. Instead, you inflate an unused "floor" layout in the Fragment and attach a room adapter to it. That layout will never be displayed anywhere so its adapter is never used.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.rvFloors.adapter = adapter
binding.rvFloors.layoutManager = LinearLayoutManager(requireContext())
// The problem is this part.
// This view isn't shown anywhere, and the views inflated in FloorsAdapter
// never get a RoomAdapter attached
ListItemControlPanelFloorsBinding.inflate(layoutInflater).apply {
rvRoomControlPanel.adapter = roomAdapter
rvRoomControlPanel.layoutManager = LinearLayoutManager(activity)
Timber.d("Inside list item")
}
Each displayed floor layout is inflated in the floor adapter in onCreateViewHolder
and the data for the floor then gets set in onBindViewHolder
. This means you need to create a separate RoomsAdapter
for each floor and attach it inside the floor adapter somewhere.
This makes accessing the room adapters more difficult with your current pattern, but if you make a Floor
object that contains both its name and its list of rooms, then the floor object selected in onBindViewHolder
can pass the list of rooms to its RoomAdapter. This means the FloorsAdapter
would take a List<Floor>
instead of List<String>
. Then in the main fragment you only need to pass the list of Floor
objects to the floor adapter and it will handle passing room lists on to the room adapters appropriately.
data class Floor(val name: String, val rooms: List<String>) {}
The floor adapter would look something like this:
// modify the ViewHolder to store the binding (so you don't have to
// re-bind the views so often) and store the room adapter for this
// floor. There should be one room adapter per floor.
inner class FloorViewHolder(val binding: ListItemControlPanelFloorsBinding,
val roomAdapter: RoomsAdapter)
: RecyclerView.ViewHolder(binding.root) {}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): FloorViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = ListItemControlPanelFloorsBinding.inflate(layoutInflater, parent, false)
// Create one adapter per floor here
val adapter = RoomsAdapter()
binding.rvRoomControlPanel.adapter = adapter
binding.rvRoomControlPanel.layoutManager = LinearLayoutManager(activity)
return FloorViewHolder(binding, adapter)
}
override fun onBindViewHolder(holder: FloorsAdapter.FloorViewHolder, position: Int) {
// for a given floor, set the rooms on that floor's room adapter
val currentFloor = floorList[position]
holder.roomAdapter.roomList(currentFloor.rooms)
holder.binding.tvFloor.text = "Floor : ${currentFloor.name}"
}
Here's an example of how that might look in the ViewModel, when it constructs the list of Floor objects, and the activity would observe the floorList
LiveData. Each Floor
contains all the data (including nested data) that it needs to display.
private val floorListLiveData = MutableLiveData<List<Floor>>()
val floorList: LiveData<List<Floor>>
get() = floorListLiveData
fun load() {
viewModelScope.launch {
val floors = mutableListOf<Floor>()
val floorList = dao.readFloors()
for(floorName in floorList) {
val rooms = dao.readRoomsInFloor(floorName)
floors.add(Floor(floorName, rooms))
}
floorListLiveData.postValue(floors)
}
}
onCreateViewHolder not called in RecyclerView
Try changing the method getItemCount like this
@Override
public int getItemCount() {
return (scheduleList != null)? scheduleList.size() : 0;
}
Related Topics
Androidruntime Error: Parcel: Unable to Marshal Value
How to Disable Sslv3 in Android for Httpsurlconnection
What Is Fatal Signal 6 in Android Logcat
Pausing/Stopping and Starting/Resuming Java Timertask Continuously
Understand Arraylist Indexoutofboundsexception in Android
How to Give Images Rounded Corners in Android
How to Allow Users to Check for the Latest App Version from Inside the App
Android Data Binding Using Include Tag
Change Position of Google Maps API's "My Location" Button
Android - Preventing Webview Reload on Rotate
Android Classnotfoundexception
How to Reliably Simulate Touch Events on Android Without Root (Like Automate and Tasker)
Writing Pcm Recorded Data into a .Wav File (Java Android)