I am making use of the Soundcloud API and displaying the search results into a RecyclerView that I have created. In my RecyclerView, each element is inside of a cardView, which contains a textView, for the title of the search result, and an imageView, for the image/album art of the result. The way that the Soundcloud API works is that when you are searching for something, it will provide you with the track IDs, titles, and other information for all of the search results. But, it does not include the album art URLs in the search result response. In order to get the album art for the search results, I must create separate JSON requests for each of the search results that I get back from the primary JSON request using the track IDs. I am perplexed on how and when to request the secondary JSONs via Volley.
Currently, I am issuing the secondary requests with the onBindViewHolder method of my RecyclerView Adapter class. This does work, but one minor problem that is present with this implementation is that when I scroll down a couple results on the screen and immediately scroll back up, some of the images get misplaced and are put into the wrong elements and the proper images take a couple seconds to load back in. This happens because the images are recycled and the onBindViewHolder method is only called when an element of the RecyclerView needs to be rendered or re-rendered. So, does anyone have a solution as to when I could make the secondary JSON requests for the album art?
You could use a ListView rather than a RecyclerView. That way your cells aren't recycled, and you don't have to worry about each cell being destroyed. The trade off is that you don't have the performance of the RecyclerView, but it might be worth it in this case.
Related
In the beginning we had listViews. As a developer, we had to recycle and reuse the views to have a fluid experience.
Then, came the recylclerviews. Now, all the recycling heavy lifting is managed by android library itself.
Using pagination, an infinite recycler view can be implemented, which loads the data when needed.
But there is one problem I am still facing in infinite recyclerview. How is the data in the adapter managed?
In most of the infinite scroll implementations of recyclerview, the new data is appended to the original data. This makes the size of data set ever increasing.
Why cant dataset itself behave like recyclerview and recycle its data, instead of appending? (Like a circular queue).
How can one manage the positions of itemviews, when the dataset is a circular queue. Is it unnecessary and yields too little performance improvement? Am I missing some design pattern?
It would be possible to clear data already loaded, but this way you have to load data not only for "bottom" views, but for "upper ones" too. So user wants to back to previous data and he needs to load that data again, that's the problem.
There could be more work about notifying data set changed in recyclerView.
You can implement it this way, but remember about pagination and how it is implemented - for example limiting data in SQL statements standard way can output different data each call, so user backing to previous data can see other results! Check Twitter pagination for one of the way to achieve same results each time.
Pros:
less data in memory
Cons:
more work to write the code
more data loading for users (more internet usage, more loading times - when users wants back to previous data)
pagination has to be designed more carefully
I get data from my server returned as an array of objects. Each object is itself an array of strings that describe the object.
For example let's use cars as the object. In this case, the array of strings are descriptors like 'year built', 'horsepower', 'automatic or manual', 'color', etc etc.
What I'd like to do is display only 1 car at a time for the user. The user can choose whether he likes or dislikes the car. Either way, a choice is final, and the next car will show up. Also, the user should not be able to go back to the previous car (not with a swipe or a clicking of aback button). In other words, he can never see his choice on the previous car again.
If I make a call to my server on every single 'like/dislike', this will be a very slow app. If I inflate a bunch of data into many views that are out of sight, it will also be a very slow app.
Most Array Adapter examples I see online illustrate how to show data bi-directionally. They are viewpagers or listviews that you can swipe left (or up) to view data that has been previously already viewed. This is not what I'm looking for.
Is there a proper way to implement what I'm trying to do? Any help will be appreciated as I'm just hoping to get some direction and can implement on my own. So far I'm thinking about possibly a viewpager that deletes items as you view them, but I have a feeling this will be really hard to manage the position of the views...
Use an array to hold the data you get from the server. You can request that the server send you 10 or 25 or 50 at a time.
Since you only want to show the user 1 at a time, and he can't scroll or swipe through the list, you only need a single set of views (enough to show all attributes of a single entry). You don't need an array adpater for this. Whenever you step from one entry to the next you just need to adjust the index into your array and then copy all the attributes of the new item into the individual views with setText() or setImageBitmap() or whatever.
I have a class that extends BaseAdapter, which I use for a ListView. In the getView() method of that class I'm using an AsyncTask with a callback method to download an image (once downloaded, I store it, so I don't have to download it again). When the ListView loads the items first, only the first item displays an image an then starts to change the images (repeatedly displaying the images of the other items). Later also the other items start showing the same behaviour. After a while they stop cycling the images and each item shows the correct images. If I scroll the ListView the items are starting again to cycle the images.
This only happens, if I recycle the convertView parameter, that is passed to getView(). If I don't the images take very long to show up, and I'm afraid I'm creating too much new Views.
Thanks in advance for any advices, to get this working properly.
The simple way to get this going is to dump all your own image loading code and use something that already handles this, like Square's Picasso. There are plenty of alternatives if you do not like Picasso.
Otherwise, your tasks will need to be aware of the recycling, so they do not attempt to update an ImageView that now needs a different image. For example, you could use setTag() and getTag() on the ImageView to store (and retrieve) the URL the ImageView currently needs, and if the image downloaded by the task is some other URL, don't apply it.
But, again, please use an existing library for this. It's 2013: few people should be rolling their own download-the-images-for-use-in-ListView-rows code anymore.
I am trying to figure out the right architecture for a list view that loads information from an http endpoint. My problem is that the information to be displayed has both text and image content. If I only load the text content the the UI is very responsive but if I also load the image content then it takes a few seconds for the list to be populated. I parse the content as it comes in and build up a list adapter but what I want to do is build up the list adapter incrementally so that the user sees the information as it becomes available instead of waiting until the last item is processed before any information is displayed. Currently I do everything with the help of AsyncTask so I'm aware of threads and how they can be helpful so I'd like to know how other people have worked around the issue of displaying list based information as quickly as possible.
So this solution doesn't incrementally build the ListView but if the text information comes quickly as you mentioned I think it might help:
Lazy load of images in ListView
Basically this solution will place a stub image in the ImageView until the desired image is finished downloading.
It is not only about loading images as far as i understand your question. Please look at "Implementing a Dynamically Loading Adapter (Endless List)" tutorial: http://codinglines.frankiv.me/post/14552677846/android-implementing-a-dynamically-loading-adapter
I enabled the Linkify property of a textview as follows:
txtbox.setAutoLinkMask(Linkify.WEB_URLS);
But, when there are URLs like bit.ly are present (which is very common nowadays in messages like tweets), it doesn't display them properly. The problem is "sometimes" it succeeds and sometimes it fails... The other problem is, if this TextView is part of a custom view for a ListView, then until I actually scroll the list somehow none of the URLs get linkified...
The other problem is, if there is an image inside a ListView, when I scroll through the list, I can see a different image load before it loads the actual image. I assume this is happening due the recycling of views, but is there any workaround for this?
But, when there are URLs like bit.ly
are present (which is very common
nowadays in messages like tweets), it
doesn't display them properly.
You don't really explain what "doesn't display them properly" means, so it is difficult to provide advice there. All I can do is point you to a project that uses android:autoLink="all", and I haven't received comments from students or readers that certain URLs aren't working.
If you succeeds/fails reference is with respect to whether or not it gets turned into a link, there may be a bug in the Linkify pattern matching algorithm. Jot down several links that fail and see if you can find a common pattern (e.g., has some funky punctuation).
if there is an image inside a
ListView, when I scroll through the
list, I can see a different image load
before it loads the actual image. I
assume this is happening due the
recycling of views, but is there any
workaround for this?
If you are populating your images immediately, I'm not aware that you will get this effect. I see this when I am loading the images based on work in a background thread (e.g., downloading the images to a cache, then updating the ImageView). One thing to do in that case is to replace the image with a placeholder in your adapter until the real image is ready.