弱引用而不是 getActivity() (Android 避免内存泄漏)?

2024-01-28

为了避免内存泄漏,我编写了以下方法,该方法将在活动中使用,并且主要在片段中使用(使用继承)。该方法应该允许我永远不会通过调用直接引用该活动

//this or getActivity()

方法是:

private WeakReference<BaseActivity> activityWeakReference = null; 

public BaseActivity getActivityFromWeakReference(){
        activityWeakReference = activityWeakReference == null ?
                new WeakReference<BaseActivity>((BaseActivity)getActivity()) :
                activityWeakReference;
        return activityWeakReference.get();
    }

正在调用这个方法getActivityFromWeakReference()代替getActivity()根据内存泄漏威胁安全吗?

如果这样做不安全,我应该退回activityWeakReference并称其为get()方法,以使其安全?

我一直在多个片段中使用它,到目前为止还没有遇到任何问题。我问这个问题是因为我读过这篇文章(here https://stackoverflow.com/a/34326285/3808178):

只要帮助者的生命周期在帮助者的生命周期内Activity,那么就不需要使用WeakReference。如果帮手 可以活得比Activity,那么你应该使用WeakReference以避免保留Activity当系统在你的对象图中 摧毁它。

到目前为止,我还没有遇到过引用元素比活动寿命更长的情况。如果您发现错误或可能的错误,请在评论中写下来。


这是完全可行的。例如,您有以下伪代码:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

         new DownloadTask().execute();
    }

    public void showInfo() {
    }

    class DownloadTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            return null;
        }

        @Override
        protected void onPostExecute(Void data) {
            // we can call showInfo() activity because Asynctask hold an implicit reference to activity 
            showInfo();
        }
    }
}

上面的代码中,有一种情况会导致内存泄漏。

解释如下:

当你创建时DownloadTask如上面的例子,java调用DownloadTask is an 内部类 https://www.tutorialspoint.com/java/java_innerclasses.htm。内部类将implicit保存对外部类的引用,在本例中是MainActivity。此外,当您启动异步任务时,系统将保留该异步任务直到其完成。例如,您下载需要 30 秒。在那 30 秒内,您旋转设备。当您旋转设备时,MainActivity is 重新创造 https://developer.android.com/guide/topics/resources/runtime-changes.html旧的活动通常会被破坏。但在这种情况下,旧的活动不会被破坏,因为旧的活动MainActivity实例由DownloadTask and DownloadTask被系统持有。您将泄漏一个活动实例。

为了解决这个问题,您应该将上面的代码更改为:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new DownloadTask(this).execute();
    }

    public void showInfo() {
    }
}

class DownloadTask extends AsyncTask<Void, Void, Void> {
    WeakReference<MainActivity> mainActivityWeakReference;

    public DownloadTask(MainActivity activity) {
        mainActivityWeakReference = new WeakReference<MainActivity>(activity);
    }

    @Override
    protected Void doInBackground(Void... params) {
        return null;
    }

    @Override
    protected void onPostExecute(Void data) {
        if (mainActivityWeakReference.get() != null) {
            mainActivityWeakReference.get().showInfo();
        }
    }
}

在这种情况下,当新MainActivity被创建,旧的不被持有DownloadTask(由于弱引用属性),所以旧的将来会被Android垃圾收集器销毁。您还应该在每次使用弱引用对象时进行检查,因为您不知道 GC 何时会销毁这些对象。

这是我自己的博客,讲述了另一种内存泄漏的情况。使用静态内部类时发生内存泄漏 https://blog.androidcafe.in/android-memory-leak-part-1-context-85cebdc97ab3

希望这有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

弱引用而不是 getActivity() (Android 避免内存泄漏)? 的相关文章

随机推荐

  • 实体框架6和空间数据

    我有具有空间数据类型的数据库 我使用数据库优先模型和实体框架 6 0 2 和 NET 4 5 当我尝试使用生成的类时 出现以下错误 指定的架构无效 错误 未加载关系 Name FK1 因为类型 Model TypeB 不可用 以下信息可能有
  • 如果 Session 不是 Active Record 模型,如何处理 :session 错误?

    没有会话模型 除了显示一般失败通知之外 如何创建有关表单提交失败原因的特定错误 回想一下第 7 3 3 节 我们使用用户模型错误消息显示注册错误 这些错误与特定的 Active Record 对象相关 但此策略在这里不起作用 因为会话不是
  • 调整标签大小以适应文本数量 - Swift

    嘿 我有一个标签 我需要根据文本量使该标签的宽度更小或更大 我只找到了如何调整文本以适合大小 但找到了如何调整大小以适合文本 有任何想法吗 你会想要这样做 myLabel sizeToFit 正如这里所见 https developer a
  • FontMetrics 设置字体?

    我正在制作一个程序 需要在 FontMetrics 对象内设置 Font 我之前已经创建了 fontmetrics 但现在我无法再访问 Graphics 对象 然而 我想更改 FontMetrics 内的字体 即创建一个新的 FontMet
  • 检测移动设备和平板电脑设备

    我目前正在研究一些用于 PHP 检测手机的代码 这可能非常简单 现在我遇到了一个问题 我希望能够在我的 MVC 框架中为平板电脑 手机和网页制作独特的视图文件 所以我需要将平板电脑与其他移动设备分开 目前这是我正在使用的代码 public
  • 内存分配 char* 和 char[]

    这两者在内存分配方面有什么区别 char p1 hello char p2 hello 第一个创建了一个pointer变量 四个或八个字节的存储空间 具体取决于平台 并存储location那里有一个字符串文字 第二个创建一个array六个字
  • jQuery 里面的点击事件为

    我真的不知道我发生了什么事 代码如下 for var j 0 j
  • Android - 努力设计帐户选择器的样式

    我正在尝试在我的游戏中实现 AccountPicker 并且我尝试使用所有三个版本newChooseAccountIntent 2 来自AccountManager和一个来自AccountPicker 我的代码看起来像这样 if andro
  • PHP 中为什么有句点? [复制]

    这个问题在这里已经有答案了 可能的重复 如果在 php 字符串中间使用 句点 字符 是什么意思 https stackoverflow com questions 6104449 what does the period character
  • 将两个 byteBuffer 连接成一个

    您好 我有 2 个 byteBuffer 我想将它们连接在一起形成一个 byteBuffer 我在这里发现了类似的问题 但那里的建议都不适合我 你可以这样做 ByteBuffer b3 ByteBuffer allocate b1 limi
  • 什么时候删除 git 功能分支合适?

    我不想结束82 个特色分支悬挂在周围 https stackoverflow com questions 2353804 list git branches that can safely be deleted 所以我想知道将功能分支合并到
  • 如何用C/C++打开Chrome扩展程序中包含的文件?

    我正在尝试在 Chrome 扩展程序中打开一个要解析的文件 例如 config txt 通过 Javascript 这将相当容易 例如 chrome extension getURL config txt 会得到类似的东西chrome ex
  • 对 Intellij 产品中的控制台输出进行着色

    我有一个带有默认输出的自定义脚本 我想对错误 警告和信息进行着色 在 Intellij 产品 IDEA PhpStorm PyCharm 中有办法做到这一点吗 已经有一段时间了 但如果您仍然感兴趣 有一个用于控制台着色的新插件 与 Inte
  • 如何避免 IntelliTrace 事件中的 EF 查询被截断?

    我正在尝试调试实体框架查询 但是 当查询变得太大时 intelliTrace 中显示的查询会被截断 即使我将其复制并粘贴到记事本中 也仅显示查询的一部分 是否有任何解决方法可以获取 EF 生成的整个查询 提前致谢 已经有一段时间了 但它可能
  • 滚动时列表视图图像发生变化

    I am 解析 json数据在一个列表视图 图像视图和文本视图 首先四项列表视图的图像和文本视图正确添加但是当我滚动列表视图时 图像视图中的图像正在发生变化 这是我的代码 适配器 java public class Adapter exte
  • 角度插值无法正常工作?

    我有一个带有插值的样本 当使用任何一个事件时 它会正确显示下拉值 如下所示 sample click me https stackblitz com edit angular 234dlf file src 2Fapp 2Fapp comp
  • MSBuild (TFS) 中的 Nhibernate.Bytecode.Castle 问题

    我们有一个 Fluent NHibernate 映射测试正在本地计算机上通过 但是当我们签入 TFS 时 测试在构建服务器上失败 我们正在使用 MSTest 我们得到的错误是 NHibernate Bytecode UnableToLoad
  • 如何在不修改代码的情况下禁用在 pytest 中跳过测试?

    我继承了一些实现的代码pytest mark skipif进行一些测试 阅读 pytest 文档 我知道我可以添加条件 可能检查环境变量 或者使用更高级的功能pytest mark将测试组一起控制 不幸的是 到目前为止 文档中似乎没有任何内
  • 字幕与文字混合

    我尝试使用以下方法将字幕与纯文本分开two空格处 我的 Rmd 文档的第一部分如下所示 title Script de Limpieza errores de digitalizacion y division de base madre
  • 弱引用而不是 getActivity() (Android 避免内存泄漏)?

    为了避免内存泄漏 我编写了以下方法 该方法将在活动中使用 并且主要在片段中使用 使用继承 该方法应该允许我永远不会通过调用直接引用该活动 this or getActivity 方法是 private WeakReference