IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 终于理解引用在 Android 和 Java 中是如何工作的 -> 正文阅读

[开发测试]终于理解引用在 Android 和 Java 中是如何工作的

几周前,我参加了Mobiconf,这是我有幸在波兰参加的最好的移动开发人员会议之一。在他不拘一格的演讲“最佳(良好)实践”中,我的朋友兼同事豪尔赫·巴罗佐( Jorge Barroso)提出了一个让我在听后反思的声明:

如果您是 Android 开发人员并且不使用 WeakReferences,那么您就有问题了。

举个好时机的例子,几个月前,我确实出版了我与Diego Grancini合着的最后一本书“Android 高性能”. 最激动人心的章节之一是谈论 Android 中的内存管理。在本章中,我们将讨论内存在移动设备中的工作原理、内存泄漏是如何发生的、为什么这很重要以及我们可以应用哪些技术来避免它们。自从我开始为 Android 开发以来,我一直观察到一种趋势,即不由自主地避免或降低与内存泄漏和内存管理相关的所有事情的优先级。如果满足功能标准,为什么还要麻烦呢?我们总是急于开发新功能,我们宁愿在下一个 Sprint 演示中呈现一些视觉效果,也不愿关心任何人第一眼就看不到的东西。

是一个很好的论点,它不可避免地导致获得技术债务。我什至要补充一点,技术债务在现实世界中也有一些我们无法用单元测试衡量的影响:失望、开发人员之间的摩擦、低质量的软件交付和动力丧失。这种影响之所以难以衡量,是因为它们往往是长期发生的。这有点像政治家:如果我只负责 8 年,我为什么要担心 12 年会发生什么?除了在软件开发中,一切都进展得更快。

写关于在软件开发中采用的体面和正确的心态可能需要几本书,并且已经有许多书籍和文章可以探索。然而,简要解释不同类型的内存引用、它们的含义以及如何在 Android 中应用它们将是一个简短的任务,这就是我在本文中想要做的。

首先:Java 中的引用是什么?

引用是被注释的对象的方向,因此您可以访问它。

Java 默认有 4 种类型的引用: 强的, 柔软的, 虚弱的 和 幻影.有些人认为只有两种类型的引用,强引用和弱引用,弱引用可以呈现 2 度的弱点。我们倾向于以植物学家的分类学毅力对生活中的一切事物进行分类。不管它对你更有效,但首先你需要了解它们。然后你就可以搞清楚自己的分类了。

每种类型的引用是什么意思?

强引用:强引用是Java中的普通引用。每当我们创建一个新对象时,默认情况下都会创建一个强引用。例如,当我们这样做时:

MyObject 对象 = new MyObject();

创建了一个新对象MyObject,并将对它的强引用存储在object 中。轻松到此为止,你还和我在一起吗?好吧,现在更有趣的事情来了。这个对象是强可达的——也就是说,它可以通过一系列强引用来访问。这将防止垃圾收集器捡起并销毁它,这是我们最想要的。但是现在,让我们看一个例子,它可以对抗我们。

公共类 MainActivity 扩展 Activity { ?  @Override 
 ?  protected void onCreate(Bundle savedInstanceState) { ? ?
 ? ? ?  super.onCreate(savedInstanceState); 
 ? ? ?  setContentView(R.layout.main); 
 ? ? ?  new MyAsyncTask().execute(); 
 ?  }
 ? ?
 ?  私有类 MyAsyncTask 扩展了 AsyncTask { ? ? ?  @覆盖
 ? ? ?  保护对象doInBackground(对象[] PARAMS){
 ? ? ? ? ?  返回doSomeStuff(); 
 ? ? ?  } ? ? ?  private Object doSomeStuff() { 
 ? ? ? ? ?  // 做一些事情来得到结果
 ? ? ? ? ?  return new MyObject(); 
 ? ? ?  } 
 ?  } 
}

花几分钟时间尝试找出任何容易出现问题的方法。

不用担心,如果不能,请多花点时间。

现在?

所述的AsyncTask将被创建并与一起执行活动 的onCreate()方法。但是这里我们有一个问题:内部类需要在其整个生命周期中访问外部类。

当Activity被销毁时会发生什么?所述的AsyncTask被保持到一个参考活动,并且活动不能被GC来收集。这就是我们所说的内存泄漏。

旁注:在我以前的生活中,我曾经对潜在的候选人进行面试时,我常常问他们你怎么能制造内存泄漏,而不是询问什么是内存泄漏的理论方面。它总是更有趣!

内存泄漏实际发生不仅当活动被破坏每本身,但以及当由系统由于需要或多个存储器的配置等的变化强制破坏如果的AsyncTask是复杂的(即,在Activity 中保留对Views 的引用,等等)它甚至可能导致崩溃,因为视图引用为空。

那么如何才能避免这个问题再次发生呢?让我们解释一下其他类型的引用:

WeakReference:弱引用是指引用强度不足以将对象保留在内存中。如果我们尝试确定对象是否被强引用并且恰好是通过WeakReferences,则该对象将被垃圾收集。对于理解而言,最好扼杀理论并作为实际示例展示我们如何调整先前的代码以使用WeakReference并避免内存泄漏:

公共类 MainActivity 扩展 Activity { ?  @Override 
 ?  protected void onCreate(Bundle savedInstanceState) { 
 ? ? ?  super.onCreate(savedInstanceState); 
 ? ? ?  new MyAsyncTask(this).execute(); 
 ?  } ?  私有静态类 MyAsyncTask 扩展了 AsyncTask { 
 ? ? ?  private WeakReference<MainActivity> mainActivity; ? ?
 ? ? ? ?
 ? ? ?  public MyAsyncTask(MainActivity mainActivity) { ? ?
 ? ? ? ? ?  this.mainActivity = new WeakReference<>(mainActivity); ? ? ? ? ? ?
 ? ? ?  } ? ? ?  @覆盖
 ? ? ?  保护对象doInBackground(对象[] PARAMS){
 ? ? ? ? ?  返回doSomeStuff(); 
 ? ? ?  } ? ? ?  private Object doSomeStuff() { 
 ? ? ? ? ?  // 做一些事情来得到结果
 ? ? ? ? ?  return new Object(); 
 ? ? ?  } ? ? ?  @覆盖
 ? ? ?  保护无效onPostExecute(Object对象){ 
 ? ? ? ? ?  super.onPostExecute(对象); 
 ? ? ? ? ?  if (mainActivity.get() != null){ 
 ? ? ? ? ? ? ?  //适配内容
 ? ? ? ? ?  } 
 ? ? ?  } 
 ?  } 
}

现在注意一个主要区别:内部类中的 Activity 现在引用如下:

私有 WeakReference<MainActivity> mainActivity;

这里会发生什么?当 Activity 停止存在时,由于它是通过 WeakReference 的方式保持的,因此可以对其进行收集。因此不会发生内存泄漏。

旁注:现在您希望更好地理解 WeakReferences 是什么,您会发现 WeakHashMap 类很有用。它的工作原理与 HashMap 完全一样,只是键(键,而不是值)是使用 WeakReferences 引用的。这使得它们对于实现诸如缓存之类的实体非常有用。

然而,我们已经提到了更多的参考资料。让我们看看它们在哪里有用,以及我们如何从中受益:

SoftReference:将SoftReference视为更强的WeakReference。而WeakReference的将立即收集,一个SoftReference的会求到GC留在内存中,除非没有其他选择。该垃圾收集算法是真正令人激动的东西,你可以潜水了好几个小时不腻。微信朋友圈怎么转发别人朋友圈但基本上,他们说“我将永远收回 WeakReference。如果对象是 SoftReference,我将根据生态系统条件决定做什么”。这使得SoftReference对于缓存的实现非常有用:只要内存充足,我们就不必担心手动删除对象。如果您想查看实际示例,可以查看这个使用SoftReference实现的缓存示例。

PhantomReference : 啊,PhantomReferences!我想我可以用一只手的手指数出我在生产环境中看到它们使用的频率。仅通过 PhantomReference 引用的对象可以在垃圾收集器需要的时候收集。没有进一步的解释,没有“给我回电话”。这使得难以表征。我们为什么要使用这样的东西?其他的还不够问题吗?我为什么选择成为程序员?PhantomReference 可以准确地用于检测对象何时从内存中移除。完全透明,我记得有两次我不得不在我的整个职业生涯中使用 PhantomReference。因此,如果他们现在难以理解,请不要感到紧张。

希望这可以让您稍微了解您之前对参考资料的看法。与任何学习问题一样,您可能希望开始变得实用,并尝试使用您的代码,看看如何改进它。第一步是查看您是否有任何内存泄漏,看看您是否可以使用这里学到的任何经验教训来摆脱那些令人讨厌的内存泄漏。如果您喜欢这篇文章或者它对您有所帮助,请随时分享和/或发表评论。那是激励业余作家的货币。

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-09-09 12:04:57  更:2021-09-09 12:05:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 21:57:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码