I need help with listview in kotlin.
I have a timer function that fetches the updated listview data every 1 minutes from the server (firebase in this case). After the firebase is done fetching the data, i apply:
listview.adapter = CustomAdapter(applicationContext)
But the problem with this is that the listview refreshes and goes up to row 1 when I may be scrolling down to row 50. This is super annoying since I have about a hundred rows.
Any body has a solution to this?
This is not relevant to Kotlin but how you use the Android APIs. You should not set a new adapter everytime the list is updated. You are just starting over from the beginning. I would recommend using RecyclerView with DiffUtil. Look at this blog for a quick example in Kotlin: https://antonioleiva.com/recyclerview-diffutil-kotlin/
Related
I am using the ListAdapter with RecyclerView and under certain circumstances the app becomes extremely slow -- it freezes for 10 seconds with a list of 1000 items.
The circumstances are, that at first I submit a list with 1000 items (at first submit its fast as expected) and then I submit the same list again, but sorted differently.
By debugging a lot, I finally found out, that the ListAdapter triggers a notifyItemRangeChanged(0, 999), so basically for the complete list. I read elsewhere (here and here), that one should not do this, because it makes the RecyclerView slow -- which apparently is true -- however, I cannot influence the behaviour of the ListAdapter.
Does anyone have a solution for that? I don't want to remove ListAdapter again, because for most other usecases it is fast and handy, doing various animations etc. automatically.
EDIT - some code
There is nothing fancy about the code, basically it's like that:
RecyclerView mListView;
EnryListAdapter mEntryListAdapter; // <-- extends ListAdapter<Entry, VH>
...
mEntryListAdapter = new EntryListAdapter();
mListView.setAdapter(mEntryListAdapter);
mListView.setLayoutManager(new LinearLayoutManager(this));
mListView.setHasFixedSize(true);
((DefaultItemAnimator) mListView.getItemAnimator()).setSupportsChangeAnimations(false);
List<Entry> entryList = getEntryList(); // <-- list with 1000 entries
mEntryListAdapter.submitList(entryList); // <-- first submit is fast
entryList = getDifferentlySortedEntryList(); // <-- list with same entries, sorted differently
mEntryListAdapter.submitList(entryList); // <-- freezes app for over 10 seconds
In the end, I found out that it was my own mistake.
In my implementation of DiffUtil.ItemCallback<Entry>#areContentsTheSame I had this check:
oldItem.flags == newItem.flags
where Entry.flags was a long first, but later on I changed it to be an instance of a class, without changing this comparison. Since the instances aren't the same objects, this comparison then resulted in false all the time. Replacing it with
ObjectsCompat.equals(oldItem.flags, newItem.flags)
fixed the issue.
I have data that was insert PostKey and Rating by cloud function. Following this picture newfeed, post
and I use FirebaseIndexRecyclerAdapter to get data
FirebaseIndexRecyclerAdapter<Post, FeedFragment.PostViewHolder> firebaseIndexRecyclerAdapter = new FirebaseIndexRecyclerAdapter<Post, FeedFragment.PostViewHolder>(
Post.class,
R.layout.post_row,
FeedFragment.PostViewHolder.class,
FirebaseRef.mNewfeedRef.child(UID),
FirebaseRef.mPostRef
) {
Solution that I was thinks is
First one is orderByValue() and load StartAt(0) to EndAt(5) when scrolled to bottom it called StartAt(0) to EndAt(10) and so on but each time will load old data that could wasted traffic.
Second one is create new reference suppose is "newfeed-post" that have only top 5 items ordered by rating that get from "newfeed" and when I scroll down to load more I request to cloud function to let cloud function insert more 5 items from "newfeed" to "newfeed-post" that lower rating (eg. position 6-10).
Please help and let me know how to do this. Thanks :D
Pagination is not supported by FirebaseUI-Android components. They currently require you to provide a single query that yields all the results to display. There is no way to progressively supply more queries as a list is scrolled. Also see the discussion in this issue on the Github repo for FirebaseUI-Android.
I wrote my own CursorAdapter for RecyclerView like following link: https://gist.github.com/skyfishjy/443b7448f59be978bc59
Then I found whenever I change something in database and want to show it in RecyclerView, I need to create a new Cursor by db.query() and use CursorAdpater's changeCursor(). Since query() will scan all rows in database, the RecyclerView will refresh slowly when data amount is big even I insert only one row into database.
Besides, as we all know, RecyclerView provides notifyItemInserted/Removed(position) for developers so that the RecyclerView can refresh partly, which is useful and beneficial to memory/time. However, when I use CursorAdapter, I don't know when and how I can use these methods because changing cursor isn't adding something directly to dataset binding with RecyclerView but refreshing all items in fact.
So are there any better ways to show data from database in RecyclerView and use RecyclerView's improving method to show variety of database?
I can tell you what i've done...
A. Loaded a cursor using Loader.
B. Copied the cursor into arraylist that is attached to the adapter (the cursor isnt attached to the adapter directly), close the cursor. Works well if there isnt a lot of data - if there is a lot rows then i would have load some of it to the arraylist and then when the user would scroll down i would query again and load from the last row of the array.
C. When the user would like to delete or add something i would do the operation on arrayList first (UI thread) notifiyItemChanged and then change the db (Back thread)
Hope i helped.
In my application I am fetching the data from a web service in XML format, and parsing it and showing the data in listview. The problem is that if the web service contains 5000 objects then it takes a lot of time to display the data.
Can it be possible to show some data in listview and fetch the data at the same time at the end of the list.
Please provide me some sample code.
If you use convertView in your ListAdapter´s getView method it should not matter how many items you have in the list since the Views are beeing reused.
If your Listadapter takes an array of som sort you could add items to the array continuosly and call
mListAdapter.notifyDataSetChanged();
every time new data is added to the list.
By Using AsyncTask you can do this easily as each object is being fetched can be shown in listview using publishProgress() method while also updating user about what percentage of data hasbeen loaded.
Update:
By the way according to your situation the tool below which is developed by commonsware https://stackoverflow.com/users/115145/commonsware will suits you best...
https://github.com/commonsguy/cwac-endless
cwac-endless: Provides the EndlessAdapter, a wrapper for an existing ListAdapter that adds "endless list" capability. When the user scrolls to the bottom of the list, if there is more data for this list to be retrieved, your code gets invoked in a background thread to fetch the new rows, which then get seamlessly attached to the bottom of the list.
Currently, I'm using AsyncTask to handle Http connection and retrieve data as JSON format.
Loading all data is trivial but it consumes too much time, so I decided to switch to load 10 items at a time using LIMIT OFFSET (mysql).
Next I set up the event onScroll for my list view to create a new AsyncTask each time user scroll. However, from what I read, AsyncTask is stored in a thread pool which is limited 5 threads at a time, so I'm not sure this is a right approach. I'm newbie to client/server app, so could I anyone give me an advice on this issue? Any related article, documentation would be greatly appreciated.
Here are few useful links for it,
Android: Implementing progressbar and "loading..." for Endless List like Android Market
Endless Listview with current Async Task
Android Endless List
http://www.androidguys.com/2009/10/21/tutorial-autogrowing-listview/
http://mylifewithandroid.blogspot.com/2010/03/progressively-loading-listviews.html
In simple steps,
As user scrolls – detect the end of the list 1)Display a progress
notification 2)Ask for update 3)Receive update (asynchronously) and
extend list
A typical approach would be e.g. to load 25 initially and then have a footer in the list that displays e.g. the current count and the total count and upon pressing loads another 25 and so on. That would be a paged sort of loading.
When you do that you have to keep the current position and notify the adapter that the list has changed.
If you are using a ListView, I believe I can safely assume that you must be using some sort of ListAdapter. Instead of starting a new AsyncTask in the onScroll event, you should maintain just one single AsyncTask to retrieve data from the server, add that data to the ListAdapter dataset and then call notifyDatasetChanged on the ListAdapter.
The ListAdapter and ListView will take care of the rest.