【问题标题】:referencing the App context from a non-static inner class从非静态内部类引用 App 上下文
【发布时间】:2014-10-31 15:43:31
【问题描述】:

我正在尝试实现一个 Android 库。在教程中,我找到了以下文本,但我不明白为什么当我有一个非静态内部类时,我无法引用 App 或 Activity 上下文?

谁能给我解释一下?

另一个常见的技巧是避免在非静态内部类中引用上下文 当您无法控制其生命周期时的活动。使用静态内部类和弱 而是对活动的引用。

【问题讨论】:

  • 您可以引用应用程序上下文,但在您无法控制应用程序生命周期的情况下,最好避免使用它。当您无法控制应用程序生命周期时,对应用程序上下文的引用可能会更改,并且您对应用程序上下文的引用将不会更新。因此,当您使用弱引用时,该引用将在 GC 之后被删除,并且您知道必须获取一个新引用。
  • @Lubo 谢谢。但是我们的 GC 和“弱引用”我不知道。
  • GC 表示垃圾收集。在 java 中,它会自动调用,或者如果您调用 System.gc()。它将搜索内存中不再引用的对象,然后将其删除。所以它释放内存用于其他目的。如果通过强引用(Object o = new Object(); 那么“o”是对对象的引用)引用了对象,则 GC 不会清除该对象,因为您有对它的引用。但是如果你使用弱引用(引用存储在 WeakReference 类中),那么 GC 将删除该对象。

标签: java android android-context


【解决方案1】:

我认为这是防止内存泄漏的一种方法。

例子:

考虑在一个需要很长时间才能完成的 Activity 中运行的 AsyncTask:

public class VeryLongRunningTask extends AsyncTask<?,?,?> {

    protected Object doInBackground(Object[] params) {
        while(runForVeryLongTime()){
            doSomethingWithContext(getContext())
        }
        return null;
    }
}

现在在您的活动的 onCreate 上运行任务

public void onCreate(Bundle bundle){
    new VeryLongRunningTask().execute()
}

如您所见,VeryLongRunningTask 将保存您的活动的引用很长时间(可能比Activity 可见的时间要长得多)。这意味着该活动将在很长一段时间内不会被垃圾收集。

【讨论】:

    【解决方案2】:

    系统只维护一个静态类的实例,因此如果内部类是静态的,则每个活动只有一个实例。如果内部类不是静态的,那么您可以在内部类上有多个实例访问活动,并且每个实例都可以独立修改活动状态。

    如果您实际上创建了内部类的多个实例,这可能会带来许多挑战。这样想,你有一个内部类,它更新 Activity 中的 counter 变量,然后根据这个 counter 的值循环遍历一个列表。如果内部类是静态的,那么只有一个实例这样做。但是,如果它不是静态的,那么可能会有三个实例这样做。请记住,所有三个都访问相同的活动和相同的 counter,因此如果它们在不同时间运行(很可能),它们将在不同时间更新变量然后循环。因此,当第一个实例更新变量并开始循环检查值时,第二个实例随后更改变量并现在影响第一个实例中的循环。然后它开始循环,然后第三个实例再次更新计数器,影响其他两个实例。所以现在内部类上以前运行的实例都不会产生正确的结果。

    这是一个非常简单的例子,事情可能会变得更糟。

    【讨论】:

    • 此信息不正确。只有嵌套类可以是静态的。但是您可以拥有嵌套静态类的多个实例。静态嵌套类和非静态嵌套类的区别在于,非静态类对外部类有隐式引用。
    猜你喜欢
    • 2011-09-01
    • 1970-01-01
    • 2012-11-02
    • 2014-12-25
    • 2019-01-07
    • 1970-01-01
    • 2011-07-06
    • 2019-03-17
    相关资源
    最近更新 更多