Recycler View is inconsistently showing/not showing data - android

The recycler view sometimes show or not show the data when I start the activity. This is how it's programmed, I have a main activity and an activity that has a recycler view in it. To test it I hardcoded a data using a for loop in the onCreate method. It will only loop and add data to the array before it is set to the recycler view. Now the problem is that, sometimes the data shows up and sometimes there's nothing in the list. I can easily reproduce the issue by going back and fort to the main activity and the activity with recycler view. I think I'm doing it wrong by adding it to the onCreate.
Here's what I have in the onCreate:
for(i in 1..5){
val newDeliveredAsset = AssetDelivered()
newDeliveredAsset.id = i
newDeliveredAsset.accountNumber = 1
newDeliveredAsset.barCode = "BB" + i.toString()
newDeliveredAsset.description = "test " + i.toString()
assets.add(newDeliveredAsset)
}
rvAsset = findViewById(R.id.ce_recycler_view)
layoutManager = LinearLayoutManager(this)
layoutManager.orientation = LinearLayoutManager.VERTICAL
rvAsset.layoutManager = layoutManager
rvAdapter = AssetRecyclerViewAdapter(this, assets as List<Asset>)
rvAsset.adapter = rvAdapter
I also tried to log the getItemSize of the adapter and it shows the correct number.
Update: Left the phone on the activity that's not showing the recycler view items. After few minutes, the items showed up.

Related

Viewpager2 is overlapping adapter view

I created a ViewPager2 view with a DiffUtil adapter, that is updated when I get data from several APIs.
However, the problem is that the views overlap when I update the adapter.
As you can see in this video.
Click to view the video on Vimeo
//viewpager
binding?.realtimeTrending?.apply {
orientation = ViewPager2.ORIENTATION_HORIZONTAL
adapter = adapter
offscreenPageLimit = OFFSCREEN_PAGE_LIMIT_DEFAULT
isNestedScrollingEnabled = true
}
// adding value to viewpager
adapter?.updateRealtime(it.value)
fun updateRealtime(value: List){
// Update the adapter when new data is available
val callback = DiffUtil.calculateDiff(DiffCallback(list, newlist))
list.clear()
list.addAll(newlist)
callback.dispatchUpdatesTo(this)
}
Please help me with the issue. I am stuck with this for a while now.

Android - recycler view scroll to position doesn't work

I am trying to retrieve data from firebase then display it in recycler view. I set the layout to be reverselayout = true. However, when I run the activity, the view starts at the bottom. I tried to change the initial position when the application is run using scrollToPosition as commented below, but still nothing changes. Does anyone have a solution related to this problem?
I've tried this: https://stackoverflow.com/a/26876044/7825519
But still start from bottom.
mRecyclerView!!.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
(mRecyclerView!!.layoutManager as LinearLayoutManager).reverseLayout = true
(mRecyclerView!!.layoutManager as LinearLayoutManager).stackFromEnd = true
mRecyclerView?.scrollToPosition(3)
// mRecyclerView?.smoothScrollToPosition(3)
// (mRecyclerView!!.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(3,0)
// mNestedScrollView?.scrollTo(0,3)
mAdapter = DiscoverAdapter(mItems, mPostKey, Static.mLikedPosts, this)
mRecyclerView!!.adapter = mAdapter
val spacingInPixels = resources.getDimensionPixelSize(R.dimen.margin_between_card)
mRecyclerView!!.addItemDecoration(SpacesItemDecoration(spacingInPixels))
First of all delete the both lines that make the recyclerview start from the botom.
Set the scrolling after you set the adapter:
mRecyclerView!!.adapter = mAdapter
mRecyclerView?.scrollToPosition(3)
Try to set scrollToPosition using post method of View

get visible item in RecyclerView

How can I get a current item in RecycerView? In my use-case RV item takes all screen space, so there is only one item at a time.
I've tried to google before, but nothing helpful was found.
The whole use case:
UI. The bottom navigation has a button that should call a certain method (let's say a foo() method) in fragment
this foo() method should get a visible item from the adapter and call a specific method in a presenter.
use this in your code
LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
and get your visible item using below code
mLayoutManager.findFirstVisibleItemPosition();
You could also use an OnItemClickListener on your RecyclerView's ListAdapter to determine the current item. In that case the item needs to be clicked though.
My solution
val position = (recyclerView?.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
val product = adapter?.getItemByPosition(position)
FirebaseCrash.logcat(Log.DEBUG, TAG, "onNavClickEvent = $product")
product?.let { productListViewModel?.order(it.id) }
The result is:
onNavClickEvent = Product(id=1, title='Cap', description='some descr.', price=10, photo='http://lorempixel.com/200/200/sports/1/')

Refreshing RecyclerView adapter every 1 second

Below is my implementation for recycler view.
The recycler view is refreshing but the view is lagging alot making it not smooth to scroll.
If I dont refresh data the recyclerView is smooth.
The problem is with refreshing only..!!
I need to refresh data completely every 1 sec in RecyclerView maintaining same scroll position.
xml
<android.support.v7.widget.RecyclerView
android:id="#+id/recyView_disp_pgms"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#null" />
Activity :
RecyclerView recyView_disp_pgms = (RecyclerView) findViewById(R.id.recyView_disp_pgms);
DisplayProgramsAdapterRecycler pgmAdapter = new DisplayProgramsAdapterRecycler(programsList);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyView_disp_pgms.setLayoutManager(layoutManager);
recyView_disp_pgms.setAdapter(pgmAdapter);
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
System.out.println("AllPgm Runflag : " + runflag);
programList = // Get List from database
if (programsList != null && programsList.size() > 0) {
if (pgmAdapter != null && pgmAdapter.getItemCount() > 0) {
pgmAdapter.resetData(programsList);
}
}
handler.postDelayed(this, 1000);
}
};
handler.post(runnable);
Adapter :
public void resetData(ArrayList<ProgramDetails_Table> programsList) {
this.programDetailsList = programsList;
this.notifyDataSetChanged();
}
Problem - Lagging scroll of recyclerView only while refreshing data for every 1 sec
Tried following other posts; but still no luck.
Please help..!!
if you want to refresh your list find your changes and then just notify that position because notifyDataSetChanged resets all of your data.
you should use lightweight notifies.something like this:
notifyItemChanged(yourPosition);
notifyItemInserted(yourPosition);
notifyItemRemoved(yourPosition);
or if you get more than one change in a range you can use:
notifyItemRangeChanged(yourPosition);//and etc
use DiffUtil. Don't use notifyDataSetChanged.
According to this https://developer.android.com/reference/android/support/v7/util/DiffUtil.html,
DiffUtil is a utility class that can calculate the difference between
two lists and output a list of update operations that converts the
first list into the second one.
It can be used to calculate updates for a RecyclerView Adapter.
Unlike the notifyDataSetChanged method, it does not reload the whole list so it has a better performance.
And you don't have to manually find the differences between the new and the old list like the other notifyData methods from RecyclerView.Adapter.
Delete your line this.programDetailsList = programsList; and add the following. This is a simple hack, a way that makes you understand Async Callbacks.
/* I have done adding one element and then deleting the same element as the last element of programsList */
/* adding and deleting triggers notifyDataChange() callback */
//add an element in index 0 as the last element into the programList
programsList.add(programsList.size() - 1, programsList.get(0));
//remove the same last element from ProgramList
programsList.add(programsList.size() - 1);
//now it works
this.notifyDataSetChanged(programsList.size() - 1);
Make sure you are calling notifyDataSetChanged() inside the resetData function.
Also, try this instead of assigning directly to programList
programList.clear();
programList.addAll(arrayListOfDataFromServer);

Get RecyclerView child Views

I am trying to get all the Views of RecyclerView items but it seems I can get only the first one. I am fetching the Views like this:
LinearLayoutManager manager = (LinearLayoutManager) rv.getLayoutManager();
List<View> list = new ArrayList<View>();
for(int i = 0; i < manager.getItemCount(); i ++ ) {
manager.scrollToPosition(i);
View view = manager.findViewByPosition(i);
if(view == null) {
Log.i("Null Check", "Null: " + i);
}
list.add(view);
}
The problem is that I fetch the first View in RecyclerView all the time. If I have 10 items, first item will be fetched and other 9 items will be logged as null. It's like scrollToPosition(i) is not working correctly.
This is scrollToPosition(i) javadoc:
Scroll the RecyclerView to make the position visible. RecyclerView
will scroll the minimum amount that is necessary to make the target
position visible. If you are looking for a similar behavior to
android.widget.ListView.setSelection(int) or
android.widget.ListView.setSelectionFromTop(int, int), use
scrollToPositionWithOffset(int, int). Note that scroll position change
will not be reflected until the next layout call.
I am worried because of this last sentence. What do you think how can I solve this?
Retrieve RecyclerView children through the assigned RecyclerView.Adapter not the layout manager. The layout manager assists in laying out children views (ie. measuring and layout) but you should be consulting the Adapter assigned to manage the RecyclerView's data and not its layout manager.

Categories

Resources