Flickering of recyclerview when fetching imagerequests - android

I experienced a flickering of the imageviews in my recyclerview when scrolling very fast. All the imagerequests would be downloaded and showed. This would a weird effect on the imageviews.
I'm using Volley library to execute the downloads, together with Picasso to show the images. Yes this is a funny combination, but I needed to customise my headers & have authentication of my requests. Picasso not allowing me this easily.
I have experimented with a lot of possibilities;
- Pausing the requestQueue when scrolling. Resume downloads when idle. This would result in the same issue, but delayed.
- Use of Volley's imageLoader/NetworkImageView. Imageloader cannot be customized like a volley request.
- Delete all requests when scrolling. Resume when idle. This would result with imageviews not being downloaded.

So as I didn't find any easy solution online, I would like to share mine.
2 lines of code that are now perfectly working with my existing code;
MyApplication.mRequestqueue.cancelAll(imgView);
imageRequest.setTag(imgView);
Then I add my request
MyApplication.mRequestqueue.add(imageRequest);
the imgView is a... ImageView
I tried with a String but behind the scenes it is checking for == and not equal, resulting in not finding and cancelling the same requests going on.
Hope this will help someone!

Related

How to make an Image Getter in a RecyclerView using fromHTML more efficient?

I'm using fromHTML to load HTML text into a TextView inside a RecyclerView element. This does work, however it is incredibly slow as the images are being loaded from a URL and when the adapter is set or updated the app freezes up or crashes and I get logs saying too much work is being done on the main thread. Is there any way to make the ImageGetter in HTML.fromHTML that I'm using more efficient and make the adapter run on a seperate thread when updating so it doesn't freeze up the app? I've tried looking at faster ways to get a Drawable but the main image loading libraries don't seem to have a way to return a Drawable object.
It looks like the line Boolean result = fiu.execute().get(); is blocking the UI thread and is defeating the purpose of the AsyncTask. You should consider using a callback in onPostExecute() to set the image.
Unfortunately, there is not a lot of information online about how to implement Html.ImageGetter. I answered a question here that addresses changing the placeholder image while the actual image loads on a simulated background thread. The solution presented in the question also works but requires manipulating and rescanning the HTML text.
I think that you could adapt something from that post to solve your problem.
Update: I think a better solution would be to use a library such as Glide to load the drawable. If the library doesn't handle your use case natively, take a look at how others have handled the limitation. See here for one approach. I think that this Stack Overflow answer may be useful to you. In onResourceReady() you can set the text with the loaded image.
Second update: I would look into Glide more. You can create a custom loader called a "ModelLoader" that can fetch your stream drawables. See here regarding how to write a ModelLoader and here for an example. (Don't know if that example works or not, but it looks OK.)

Android MVVM: Does using Glide directly in a fragment break the MVVM pattern?

I'm trying to follow the MVVM pattern in a new App I'm currently writing.
Basically it gets a list of items in JSON from my REST-Backend and displays it in a RecycleView inside my fragment.
I created a repository, which fetches the data and hands it over to the ViewModel which has LiveData which is observed by the fragment.
That all works fine.
But: Every item also has a url for an icon. When the list is fetched, for every item I want to load the icon from this url into a ImageView.
Actually I am using Glide to directly (asynchronously) load the icon into the corresponding ImageView - which is good for UX and performance (in my opinion), since the user already sees data while the icons load in the background
My question:
Does using Glide directly in the fragment break the MVVM pattern?
What's an alternative approach to that?
E.g. loading the icons in the Repository, updating the RecycleView every time a icon is fetched (bad performance)?
In my opinion, I think it break MVVM but I think it still ok
Example: If we don't use any library for load image from url, we will create a function to get the bitmap from url (like ImageRepository#getImageBitmap(url)), after we receive the bitmap, we will use it to display into ImageView.
Why getImageBitmap(url) should be inside Repository? // because it get data from server
However, image loading library handle all for us and it support many great things and also loading image from url just a small task (and we don't need to test it if we using library). Therefore, I think we can load image inside View (Activity,Fragment,...) to make coding easier without any problem.
If we use another approach (like your approach), code will become more complex and also we need more time to test.
This is just my opinion, hope it help
you can use BindingAdapters to set the image from XML itself. I think it's a much more cleaner approach, so that UI related changes goes with inside the XML
#BindingAdapter("imageUrl")
fun setImageUrl(imageView: ImageView, url: String?) {
GlideApp.with(imageView)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageView)
}
Loading an image is something called "low level detail". In other words it's something that Architecture should not care about. Hence If you use Glide or Picasso it's not relevant to Architecture of the app. Based on this your current state is "ok", however your suggestion for alternative way of doing thing can cross so many red lines.
Skim through Uncle Bob's Clean Architecture for more details.

NavigationView lag with network Image using Glide

I have an activity with a viewpager displaying three fragments. The third fragment is a basic recyclerview using a grid layout manager.
The grid items are basic image and title items nothing complex and I am using Glide to load images.
The problem is this, when I try opening/closing the NavigationView drawer when on this page, it lags very badly.
This is what I've noticed, the lag only happens when I load an image from a url. Local drawables are fine, and the drawer opens smoothly. I'm at a loss and have no idea where to look anymore.
I would post code, but I am not sure which part to post. If you need to see some portion, please ask and I'll do so. Moreover I feel it's not from the code.
UPDATE:
I continued debugging and decided to test the same code using Picasso. This time, it works perfectly, there is no lag at all and it works like it should. No idea why. I am going to raise a ticket on Glide's github.
After hours more of debugging and even trying to use Fresco (usage sucks),
I finally solved the problem.
I had to use dontTransform(). Apparently, this is affecting all pages where I have large images like grids. This solved the problem for me.

LruCache and Concurrent acces gridview / listview with BitMap from files in Android

Before write this thread, I read a lot of stackoverflow thread, and also many tutorial.
I think people maybe some times write tutorial only to "write something".
I use a gridview to show file (imageView+textView) from files
I've got my File's list called files. I set up a Custom BaseAdappter. It worked very well, because rather in a folder I' ve got more than 5 image. So in adapter I can call 3 different method from imageView: imageView.setImageResource(), setImageBitmpa(), setImageUri(). I used the last, because I can call Uri.fromFile(file) after get current file in adapter.
I found big problems when go to "DCIM/Camera" folder. Here, my apps work without crash. Scrool is really fast. This, because I follow all google developer instructions to manage bitmap.
So, now my adater use AsynkTask and also a LruCache. The example by official google developer page use methods where bitma is decoded from resource. So I had to edit some line, and change decodeResource() in decodeFile();
this last method want fileName, and Options. So, my app show "well" all image from default gallery folder, but with a big problem.
After a totally load of gridview, if I scrool down 20 row (example), and return at position 0 scrolling up, many imageView are changed with other image. This problems happens all time I do a little or large scrool.
I cannot post any Log, any Error, because AS not show me any Error. Only some time Log show me something like "WaitForConcurrentGcToComlete blocked..."
Thanks

Android Lazy loading without ListView

I am looking to implement lazy loading in my app and I cannot seem to get it done. I've looked everywhere and nothing seems to be working.
My app is a news app making a SQL query to my wordpress website and getting the image URL and the article title associated to the image. The thing is I cannot use list views for this app because I want the first article to be a way bigger image that takes a third of the screen and the title placed on the image (the same way it is done in this image : http://iphone-apple.fr/wp-content/uploads/2010/06/lequipe2-iphone.jpg).
To create the design I have used RelativeLayout. Each article is a RelativeLayout composed of an ImageView and a TextView.
My problem is that all of the tutorials I found on lazy loading for ImageViews on the internet are for ListViews.
I have tried AsyncTask but it did not work. It actually worked but it showed all of the images at the end of the load so I had a black screen for about 5-10 secs before showing the main activity.
Does anyone have any idea how I could proceed ?
Thanks a lot for all of your answers ! :)
May be you are working with Native Emulator that work in slow environment.Install bluestack emulator or try to work on some android device

Categories

Resources