Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do you use ReleasableReferences? #1117

Closed
ronshapiro opened this issue Mar 26, 2018 · 14 comments
Closed

Do you use ReleasableReferences? #1117

ronshapiro opened this issue Mar 26, 2018 · 14 comments

Comments

@ronshapiro
Copy link

Almost 2 years ago, we added the dagger.releasablereferences package (@CanReleaseReferences, ReleasableReferenceManager, etc) to give users a mechanism to have regular scoping considerations (only use this one instance anywhere in my component) but also allow for the objects to be garbage collected under memory pressure if they weren't being referred to.

As far as we can tell (from internal code searches, public github projects, github issues, and ASG) there doesn't appear to be much, if any, usage of the feature, so we're considering getting rid of it to burn down some technical complexity.

Before we do so, we wanted to see - is anyone planning on beginning to use the feature, or perhaps didn't know about the feature but upon reading this message thinks it could be useful? If so, please reach out to us to discuss.

If we don't hear of anyone, we'll plan on removing the feature sometime soon. Given that it is marked @Beta we can remove it, but we'd like to understand any usages that exist to see if the feature was ever used appropriately.

@ashdavies
Copy link

I introduced an implementation of ComponentCallbacks2 in our project to release the references for anything application scoped when onTrimMemory had been called, but I've been too apprehensive about enabling it for production builds so it's just been in our development builds, I couldn't say I've noticed any issues or major benefits either way though.

@TWiStErRob
Copy link

TWiStErRob commented Mar 27, 2018

Downvoted to signify not using, never heard about it.
(@ronshapiro maybe clarify which reaction to use for what response)

@markuspfeiffer
Copy link

Put me into the "didn't know about the feature but upon reading this message thinks it could be useful" crowd :) I've been using ComponentCallbacks2 for that purpose, but it's kinda clunky and this looks like a much better solution.

@ronshapiro
Copy link
Author

FYI, the thumbs up/thumbs down aren't so helpful, because they could mean that you support the removal/you like the feature or don't like the idea of removal/don't like the feature/didn't know about it.

@ronshapiro
Copy link
Author

@markuspfeiffer can you describe a little bit more about what you are currently doing?

@markuspfeiffer
Copy link

It's a fairly ugly construct (imho) that I'm so far only using for a single module. The module itself implements ComponentCallbacks2 and is registered in the application when the injector is created.

@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
    final ApplicationModule module = new ApplicationModule(this);
    this.registerComponentCallbacks(module);

    return DaggerApplicationComponent.builder()
            .seedModule(module)
            .create(this);
}

Instead of using a scope annotation on the @Provides method, I've added my own caching for the instance that is created. In the onTrimMemory(final int level) method I clean up the instance based on the level of memory pressure.

I didn't want to use a simple WeakReference because that would mean the instance is cleaned up whenever. Instead I wanted to clean up the instance when it's clear it hasn't been used for some time and is likely not going to be used in the near future. This way I can free memory when it's not needed but avoid reconstructing the instance each time it's injected (because construction takes some time).

@ronshapiro
Copy link
Author

Ok, it seems like the our assumption that most people are unfamiliar is correct. I think we'll start removing it then.

@ronshapiro ronshapiro mentioned this issue Apr 19, 2018
ronshapiro added a commit that referenced this issue Apr 19, 2018
See #1117

RELNOTES=Deprecate `dagger.releasablereferences`

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=193093600
ronshapiro added a commit that referenced this issue Apr 19, 2018
See #1117

RELNOTES=Deprecate `dagger.releasablereferences`

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=193093600
ronshapiro added a commit that referenced this issue Apr 19, 2018
See #1117

RELNOTES=Deprecate `dagger.releasablereferences`

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=193093600
@davidxiasc
Copy link

I think it would be useful to have a scope where the references are weak by default. This would allow developers to keep static references to components without necessarily incurring the memory overhead of instantiating all dependencies even when the dependencies are no longer used.

The reason I find this useful is as follows: I wish to write a library that uses dagger to make developing and testing easier, but I don't want to expose the component itself. If I still want to make it easy for consumers to then access specific singleton dependencies, then I need to keep a static ref to the component. But then, it seems that there's no way for these objects to be gc'd if no one is using them anymore.

Not sure if there is something that already exists or if there is a more elegant solution to this problem.

@TWiStErRob
Copy link

@davidxiasc I think in that case I wouldn't expect a Singleton. If I decide to use a single instance, I'll keep a reference to it in my own way, you just create a builder/factory to create and let users decide how to use. See Picasso.with() (former get()) and Picasso.Builder.build() as an example.

@davidxiasc
Copy link

Hmm I'm referring to more of a situation where you'd want a single source of truth but don't really care if it gets deallocated and reallocated.

Imagine I have a data source that persists data to disk/server on write, but holds an in-memory cache. I don't really if this object is deallocated because I can always create a new one that recovers from the state written to disk/server. However, if multiple instances are allocated, one instance may end up holding a stale cache

@trevjonez
Copy link

trevjonez commented Jun 6, 2018

I think @TWiStErRob 's point still holds true in that you as the user of dagger can easily add the weak ref behavior you are after without it needing to be built directly into the dagger compiler/runtime.

You could make the provides method be un-scoped then just add a double check lock around whatever cache/invalidation or maybe even memory aware logic. And perhaps it is just a double check lock around a weak reference, but this doesn't matter to dagger, it is just an implementation detail of your project.

@bmeike
Copy link

bmeike commented Jun 21, 2018

I find this annotation useful. It is, in fact, what I thought @reuseable did. I only found this when I got evidence that @reuseable was not doing what I expected (it creates un-GCable singletons). While I take @TWiStErRob point, Dagger is the factory from which I get my instances. It seems at least plausible, to me, to keep this control in that factory.

ronshapiro added a commit that referenced this issue Oct 31, 2018
Closes #1117

RELNOTES=Removed `dagger.releaseablereferences`

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=219375134
@ronshapiro ronshapiro mentioned this issue Oct 31, 2018
ronshapiro added a commit that referenced this issue Nov 1, 2018
Closes #1117

RELNOTES=Removed `dagger.releaseablereferences`

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=219375134
@philbrown-mdt
Copy link

philbrown-mdt commented Sep 17, 2019

@ronshapiro is there anything to replace this feature? We are using 2.11, and we actually do use ReleasableReferences. Basically we have our own mechanism for handling scope within Activities and other lifecycle-related objects in Android (services, broadcast receivers, etc). Is the replacement simply to use dagger-android? Are there docs for this migration or can you add them?

@ronshapiro
Copy link
Author

ronshapiro commented Sep 18, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants