最终了解引用在 Android 和 Java 中的工作原理

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

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

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

每种类型的参考是什么意思?

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

我的对象对象 = 新的我的对象();

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

公共类 MainActivity 扩展 Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

设置内容视图(R.layout.main);

新的 MyAsyncTask().execute();

}


私有类 MyAsyncTask 扩展 AsyncTask {

@Override

受保护对象 doInBackground(Object[] params) {

return doSomeStuff();

}

private Object doSomeStuff() {

//做一些事情来得到结果

return new MyObject();

}

}

}

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

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

现在?

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

当Activity被销毁时会发生什么?AsyncTask持有对Activity的引用,并且Activity无法被 GC 收集。这就是我们所说的内存泄漏。

旁注:在我以前的生活中,当我曾经与潜在候选人进行面试时,我曾经问他们你如何造成内存泄漏,而不是询问内存泄漏的理论方面。它总是更有趣!

内存泄漏实际上不仅发生在Activity本身被销毁时,而且还发生在由于配置更改或需要更多内存等而被系统强制销毁时。如果AsyncTask很复杂(即,在Activity中保留对Views的引用等)它甚至可能导致崩溃,因为视图引用为空。

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

WeakReference:弱引用是一个引用不够强,无法将对象保留在内存中。如果我们尝试确定对象是否被强引用并且它恰好是通过WeakReferences,则该对象将被垃圾收集。为了便于理解,最好摒弃理论并作为一个实际示例展示我们如何调整以前的代码以使用Wea​kReference并避免内存泄漏:

公共类 MainActivity 扩展 Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

新的 MyAsyncTask(this).execute();

}

私有静态类 MyAsyncTask 扩展 AsyncTask {

private WeakReference mainActivity;


public MyAsyncTask(MainActivity mainActivity) {

this.mainActivity = new WeakReference<>(mainActivity);

}

@Override

受保护对象 doInBackground(Object[] params) {

return doSomeStuff();

}

private Object doSomeStuff() {

//做一些事情得到结果

return new Object();

}

@Override

protected void onPostExecute(Object object) {

super.onPostExecute(object);

if (mainActivity.get() != null){

//调整内容

}

}

}

}

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

私有 WeakReference mainActivity;

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

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

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

SoftReference:将SoftReference视为更强的WeakReference。WeakReference将立即被收集,而SoftReference将请求 GC 保留在内存中,除非没有其他选择。垃圾收集器算法非常令人兴奋,您可以潜入数小时而不会感到疲倦。但基本上,他们会说“我将永远收回 WeakReference。如果对象是 SoftReference,我会根据生态系统条件决定做什么”。这使得SoftReference对于缓存的实现非常有用:只要内存充足,我们就不必担心手动删除对象。如果您想查看实际示例,可以查看使用SoftReference实现的缓存示例。

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

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章