防止线程被垃圾收集,并防止上下文泄漏

时间:2015-05-22 10:47:24

标签: android multithreading memory-leaks garbage-collection accountmanager

我想自定义从AccountManager获取身份验证令牌的过程。

AccountManagergetAuthToken()getAuthTokenByFeatures()方法,但我想实现自定义流程,包括在活动之间切换等等。

我想通过以下方式实现它:

public AccountManagerFuture<Bundle> getAuthTokenForActiveAccount() {
    GetAuthTokenForActiveAccountFuture future =
            new GetAuthTokenForActiveAccountFuture(MyActivity.this);
    future.start();
    return future;
}

在我的活动中使用以下嵌套类:

  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;
    }
}

我的想法是我可以创建自己的AccountManagerFuture对象&#34;取消阻止&#34;只有在完成所有必需步骤后才会使用getResult()方法(其中一些步骤包括活动切换)。

我在这里遇到两个问题:

  1. 我需要Activity上下文以便在必要时切换到其他活动,但是当我切换到其他活动时,我应该销毁传递给构造函数的Activity,但它不会因为我的{{ {1}}拥有对它的引用......所以我在这里创建了一个内存泄漏。似乎使内部类非静态无法解决此问题 - 从Thread返回的引用仍将阻止外部getAuthTokenForActiveAccount()被垃圾回收。在没有泄露背景的情况下,有什么办法可以实现我的目标吗?
  2. 一旦Activity方法返回,
  3. Thread就有资格进行垃圾回收,对吧?但在我的情况下,我希望这个线程能够继续存在,因为它也可以作为run()运行 - 它应该保存在内存中,直到所有对它的引用都消失为止。我的问题是:是否足以保留(强)引用AccountManagerFuture以防止它被垃圾收集?如果没有,我怎么能强迫这个Thread坚持下去,直到所有的引用都消失了?

2 个答案:

答案 0 :(得分:1)

起初。 Making your Future non-static would make it having an implicit reference to its outer class - the Activity

  1. 您应该在未来与活动之间使用某种形式的间接通信。无论如何,您应该将其转移到服务中 - 您是否考虑过任何配置更改?你在哪里为你的未来提供参考? 我会建议你将你的流程转移到片段 - 然后你就不必转换活动 - 并将你的未来放入一个保留的片段(以使其在方向改变中存活下来)或将其转移到后台服务并与你的活动进行交流(或任何类型的UI)通过广播接收者或事件总线。

  2. 只要您保留一些引用线程,就不会对线程进行垃圾回收。无论是否完成。我认为你很困惑这个事实是即使没有保持对它的引用,正在运行的Thread也不会被垃圾收集。 (我想JVM会这样做,但我不得不承认我对此不确定)

答案 1 :(得分:0)

问题1解决方案:
使用私有WeakReference mContextHolder。当你需要上下文时 - 调用mContextHolder.get()并检查null;

问题2解决方案:
使用托管您线程的服务。