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, but Activity

    I pass the constructor to be destroyed when I switch to another activity, but it's not because mine Thread

    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 from getAuthTokenForActiveAccount()

    will still prevent collection of the outer one Activity

    . 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 returns run()

    , right? But in my case, I want this thread to hang because it also functions like AccountManagerFuture

    - 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) reference Thread

    to prevent garbage collection? If not, how can I get this one Thread

    to stick until all links are gone?
+3


source to share


2 answers


First. Making your Future non-static will result in it having an implicit reference to the outer class - Activity .



  • 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)

+1


source


problem 1:
use private WeakReference mContextHolder. when you need context, call mContextHolder.get () and check for null;



problem 2:
Use a service that will host your streams.

0


source







All Articles