bumptech / glide

An image loading and caching library for Android focused on smooth scrolling
https://bumptech.github.io/glide/
Other
34.67k stars 6.12k forks source link

Create Custom Life cycle #1148

Closed thedumbtechguy closed 8 years ago

thedumbtechguy commented 8 years ago

Hello.

I've created my own library replacement for Fragments that relies solely on views and has provides a life cycle for the Pages.

The issue I'm having is, when I load images and remove the views from the parent, after a few more such actions, I hit an OOM. I've pinpointed this to the fact that glide is tying into my Activity life cycle and seems not to be releasing the drawables.

I've gone through the various overloads for Glide.with and it's clear that this is not going to be trivial to extend glide to do.

Is there a way to call custom methods on glide to trigger the various events? Or will using the application context help?

If not, I'm looking at using Kotlin to add extension methods to the various classes to get this functionality though I'd rather opt for a better way.

Thanks.

TWiStErRob commented 8 years ago

Hmm, interesting use case. Bold move to ditch Fragments :)

Is there a way to call custom methods on glide to trigger the various events?

App-context will make it worse: http://stackoverflow.com/a/32887693/253468

Is there a way to call custom methods on glide to trigger the various events?

Glide follows the lifecycle of Activity/Fragment by adding a view-less fragment into them, so it is start/stopped along with its parent. This means that you would have to be able to host a fragment inside your pages (FragmentHostCallback?), which kind of defeats the purpose of writing your own lib. I don't think you can extend Glide.with, but you can create your own probably. For example add a RequestManager glide() method to your Page implementation, which does something like RequestManagerRetriever#fragmentGet. Take a look at that method and related classes. If you can produce a RequestManager tied to your Page you're good to go.

All the above is so you have an automated version which will kill all requests when the context dies. There's another approach which gives you tight control and much responsibility. Use Glide.with(activity) and call Glide.clear(imageView) when your Page is dying. This is easy with simple view hierarchy when you control all the ImageViews, but as soon as you want a list/recycler it becomes harder, but not impossible: I tried to do Fragment.onDestroyView -> list.setAdapter(null) + Adapter.onViewRecycled -> Glide.clear(holder.imageView) and it seems to work. Clearing the adapter forces onViewRecycled, but that method is not called when the list is just garbage collected.

thedumbtechguy commented 8 years ago

Wow! That's very thorough. I really appreciate the help. I found out about the problems with Application after posting so that's not an option anymore. Indeed, I did think of adding creating a fragment and using that, so it's nice to find out that that's how Glide works internally. Glide.clear was an option, but since I'm hoping others use it, it's not a very scalable solution.

I've been looking and I just might be able to extend or at the very least provide my own Request manager instance like you suggested. That's looking like the easiest option now. I'll keep you posted. Once again, I really appreciate the thorough response. If you want, you can check out my repo https://github.com/frostymarvelous/Folio. It's undocumented at the moment so you'd need to look at the sample to get an idea of what I'm aiming for.

On Sat, Apr 23, 2016, 2:39 PM Róbert Papp notifications@github.com wrote:

Hmm, interesting use case. Bold move to ditch Fragments :)

Is there a way to call custom methods on glide to trigger the various events?

App-context will make it worse: http://stackoverflow.com/a/32887693/253468

Is there a way to call custom methods on glide to trigger the various events?

Glide follows the lifecycle of Activity/Fragment by adding a view-less fragment into them, so it is start/stopped along with its parent. This means that you would have to be able to host a fragment inside your pages ( FragmentHostCallback?), which kind of defeats the purpose of writing your own lib. I don't think you can extend Glide.with, but you can create your own probably. For example add a RequestManager glide() method to your Page implementation, which does something like RequestManagerRetriever#fragmentGet. Take a look at that method and related classes. If you can produce a RequestManager tied to your Page you're good to go.

All the above is so you have an automated version which will kill all requests when the context dies. There's another approach which gives you tight control and much responsibility. Use Glide.with(activity) and call Glide.clear(imageView) when your Page is dying. This is easy with simple view hierarchy when you control all the ImageViews, but as soon as you want a list/recycler it becomes harder, but not impossible: I tried to do Fragment.onDestroyView -> list.setAdapter(null) + Adapter.onViewRecycled -> Glide.clear(holder.imageView) and it seems to work. Clearing the adapter forces onViewRecycled, but that method is not called when the list is just garbage collected.

— You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub https://github.com/bumptech/glide/issues/1148#issuecomment-213751263

TWiStErRob commented 8 years ago

I don't think you need to extend RequestManager, just create it by providing the objects required by the constructor.

thedumbtechguy commented 8 years ago

That's actually what I meant.

thedumbtechguy commented 8 years ago

I've almost got it figured out but I want to be sure of one thing. Is it safe to provide a RequestManagerTreeNode that has no descendants? What are the possible side effects?

TWiStErRob commented 8 years ago

I think just check (source/debug) if the built-in tree returns itself in the descendant list; that may be a key point.

Otherwise I think the reason it exists because fragments can be nested via getChildFragmentManager. As far as I could tell your pages could be nested too, but as a first proof of concept I don't t think it's needed, just make sure you remember this ;)

Not sure what the descendants are used for, check that method's usages / data flow from there in IDEA.