I need to manipulate a ListView's children when it is done loading, but I can't seem to find a way to find out when this happens. When I set the adapter of my ListView, the method returns immediately, but the population of it's children views happens asynchronously. Is there a way to handle the event when my list is full of views?
You can either do a periodic polling to see if the list has been populated: write a while() loop to check once in a while. Or you could wait for a fixed amount of time (say 30 ms) before doing your next operation. These are not recommended methods, but should solve your problem.
Use getChildCount() to retrieve the shown views and also use a counter to keep track of how many views have been loaded asynchronously. I think I understand your question right.
Related
Is is possible to have race conditions between the notify* methods of a RecyclerView.Adapter and scrollToPosition (and smoothScrollToPosition) of the RecyclerView itself? If so, how can I force the scroll to happen strictly after the notify has been applied?
In a bit more detail: I have a RecyclerView with an adapter that frequently is updated with new items (which may or may not overlap with the previous items). Also, whenever I set new items I also want to set the scroll position to a specific item. To that end, I first update the items inside my Adapter and then scroll the RecyclerView.
However, more often than not the scroll position will be wrong after this process. Also, if I then issue another smoothScrollToPosition command without changing the data, the scrolling is weird: It sometimes goes in the wrong direction, etc. After this second scrolling, the position is always correct however. So, it seems that something goes wrong the first time and the RecyclerView catches and corrects that error on the second scroll.
Also, the errors are slightly different when I use notifyDataSetChanged from when I use DiffUtil.
Now I've read in this response by Yigit that notify* is basically asynchronous, so I suppose there can be a race condition between them and the subseqent scrollToPosition - is that correct?
Finally what can I do to establish a strict ordering, so that the scroll is only called when all ViewHolder updates triggered by notify are done?
I need to implement the next logic in Android:
We have RecyclerView with hours of days (8.00-17.00, after 17.00 we see 8.00 of the next day, so the list is infinite) and should add events according to their time. I implemented it using LinearLayoutManager and view holder is a day where I add events to absolute position of view). But I don't like this way, because every item view is a bit havy and list doesn't scroll smoothly when draws new item. Please help me find correct way to implement it.
If the scrolling is not smooth then probably your onBindViewHolder is too heavy. There is no generic advice in this situation. You need to run Android Studio->Android Monitor->CPU->Start Method Tracing and analyse what actually slows down creating day view. Then optimise that part.
Also carefully check if you are not running any disk or database access code in UI thread. Move it to a separate thread.
I'm using recycler view with grid view (every item contains a grid) with thumbnail images after adding images in view it start uploading, and i need to change some values (status) in model at the time of start and finish upload.
What I'm currently doing is change values in model and call notifyDataSetChanged, but it causes to slow down application (hang some times) because it updating every child of list :(
Can any one help me with this?
Call notifydatasetchanged() for particular Gridview adapter only. Don't call notifydatasetchanged() for complete recyclerview adapter.
Try setting it again to the adapter.
gridview.setAdapter(your adapter)
-passing your new list to your adapter.
I believe notifyDataSetChanged updates all of your values regardless if they have a change or not that is why it is slow. I suggest you try using notifyItemChanged(int position) instead.
According to recyclerview docs this is what notifyDataSetChanged does:
This event does not specify what about the data set has changed, forcing any observers to assume that all existing items and structure may no longer be valid. LayoutManagers will be forced to fully rebind and relayout all visible views.
Old question but similar to what I'm experiencing.
RecyclerView is usually incredibly fast when changing list details. But manipulating a lot of images can really slow it down if you're not careul.
I'd recommend you try removing the images and repeat it so you can see if that is just as slow. I suspect this will be a lot faster.
If so, make sure you're handling the images off the UI thread. The Android docs recommend you use a library such as Glide which also handles sub-sampling the image to make sure it's the right size.
Hope that helps!
I have a ListView that I am calling smoothScrollBy() on. 95% of the time, the smoothScrollTo() behaves as intended. However there are times that it does not end up in the intended spot! I have verified that I am giving it the same value. I notice that the smooth scrolling is not so smooth when the errors are made, however there are no other tasks that my application is performing that I would have control over.
I am not quite sure what is going on in the background but a likely culprit is garbage collection.
95% accuracy is not good enough in this situation. I am going to have to implement some sort of a correction mechanism to make sure the ListView lands on the correct spot in these instances.
Is there a better way to use smoothScrollBy() other than simply calling view.smoothScrollBy(distance, time);?
sometimes it will be because of the timing issue. When the views are added to your listview and the time you do
view.smoothScrollBy(distance, time);
the listview or the ui still need not get refreshed. So do this in the views post thread with a specific delay. Eg.
view.postDelayed(new Runnable{
view.smoothScrollBy(distance, time);
},1000);
Try some of these:
Listview has its own scrolling mechanism. It scrolls when the content is added.
Assign listview height (android:layout_height) to match_parent or fill_parent.
If your assigning a adapter in a working thread. Do not perform any UI actions in the thread.
If these do not solve the issue. Please post the code where you assign the adapter to the list view if any. Or the relevant code.
Also the xml layout code.
Hope this helps.
Is there a way to call BaseAdapter.notifyDataSetChanged() on a single element in the adapter.
What I am trying to do is update the data and reflect those changes in the containing ListView. The problem is that sometimes the change is so small that it seems ridiculous that I have to refresh the whole view rather than the single item in the view that has been updated.
I am not aware of such method. If it's really important, you can always find individual item view to update. But I don't think that it worth it as Android is pretty efficient in updating list views. So it will not do much extra work (definitelly not going beyond items currently visible on the screen).