Prevent garbage collection and prevent context leaks
I want to customize the process of getting an authentication token from AccountManager .
AccountManager
has methods getAuthToken()
and getAuthTokenByFeatures()
, but I want to implement a custom flow that includes switching between activities, etc.
I wanted to implement it like this:
public AccountManagerFuture<Bundle> getAuthTokenForActiveAccount() {
GetAuthTokenForActiveAccountFuture future =
new GetAuthTokenForActiveAccountFuture(MyActivity.this);
future.start();
return future;
}
Using the following nested class in my activity:
private static class GetAuthTokenForActiveAccountFuture extends Thread implements
AccountManagerFuture<Bundle> {
private final Activity mActivity;
public GetAuthTokenForActiveAccountFuture(Activity activity) {
mActivity = activity;
// TODO: write this method
}
@Override
public void run() {
// TODO: write this method
}
@Override
public boolean cancel(boolean b) {
// TODO: write this method
return false;
}
@Override
public boolean isCancelled() {
// TODO: write this method
return false;
}
@Override
public boolean isDone() {
// TODO: write this method
return false;
}
@Override
public Bundle getResult() throws
OperationCanceledException, IOException, AuthenticatorException {
return internalGetResult(null, null);
}
@Override
public Bundle getResult(long timeout, TimeUnit timeUnit) throws
OperationCanceledException, IOException, AuthenticatorException {
return internalGetResult(timeout, timeUnit);
}
private Bundle internalGetResult(Long timeout, TimeUnit timeUnit) throws
OperationCanceledException, IOException, AuthenticatorException {
// TODO: write this method
return null;
}
}
My idea was that I could create my own AccountManagerFuture and "unblock" its method getResult()
only after all the necessary steps (some of which involve switching activities).
I have two questions:
- I need a
Activity
context to switch to other activities when needed, butActivity
I pass the constructor to be destroyed when I switch to another activity, but it's not because mineThread
contains a reference to that ... So I'm creating a memory leak here. It seems that making the inner class non-stationary will not solve this problem - the reference returned fromgetAuthTokenForActiveAccount()
will still prevent collection of the outer oneActivity
. Is there a way to achieve what I am trying to do without skipping the context? -
Thread
is eligible for garbage collection after the method returnsrun()
, right? But in my case, I want this thread to hang because it also functions likeAccountManagerFuture
- it has to be kept in memory until all references to it are gone. My question is this: is it enough to contain a (strong) referenceThread
to prevent garbage collection? If not, how can I get this oneThread
to stick until all links are gone?
source to share
-
You have to use some kind of indirect connection between your future and your actions. You should probably move it to Service - have you thought about any configuration change? Where do you keep the link to your future? I would advise you to either move the stream to fragments - then you don't have to switch to actions - and put your future in a saved fragment (so it can survive the orientation change), or move it to a background service and communicate with your actions (or any UI) via broadcasts or the event bus.
-
A thread will not be garbage collected if you keep some reference to it. Whether it's finished or not. I think you are confusing this with the fact that a running thread will not collect garbage even without referencing it. (I think the JVM does this, but I must admit I am not sure about this)
source to share