内存泄漏基本上是从内存中释放未使用的对象的失败。作为开发人员,您无需考虑内存分配,内存释放和垃圾回收。所有这些都是垃圾收集器自行执行的自动过程,但是当用户引用不再使用的对象,但由于该对象被另一个对象引用时,对于垃圾收集器来说,情况就变得困难了,垃圾收集器认为未使用的对象正在被另一个对象使用,并且由于该垃圾收集器不会释放该对象的内存,因此,可用堆内存会减少,从而导致内存不足和内存泄漏。未释放的对象基本上称为泄漏。
内存泄漏是android应用中应用崩溃的常见原因。每个开发人员都必须知道如何避免内存泄漏以及在什么情况下会导致android应用程序中的内存泄漏。当不再释放RAM资源且不再需要它们时,如果执行了几次,则操作系统分配给该特定应用程序的内存部分可能会超过上限,并且系统可能会终止该应用程序,从而导致应用程序崩溃。持有不再需要的对象和资源的引用是android应用程序中内存泄漏的主要原因。众所周知,特定对象的内存是在堆中分配的,并且该对象使用某些对象引用指向某些资源。但是,当工作完成时,应该释放对象引用。但是,如果不这样做,堆空间就会不断增加,并且应用程序的其余部分必须在剩下的任何堆空间上运行,最终很有可能导致应用程序中的内存泄漏。因此可以说,内存泄漏是我们的应用程序内存不足时使用的术语,因为某些未使用但仍由引用指出的对象会不断占用堆空间,最终导致内存不足应用程序其他组件的空间不足,从而最终导致应用程序崩溃。
Note: One needs to remember that whenever there is a shortage of space in the heap and the system needs to allocate space for some new objects, the garbage collector is being called in the frequent intervals, causing to slow down of the application or sometime the application may crash.
内存泄漏的原因及其解决方案
1.使用静态视图
在开发应用程序时,不应使用静态视图,因为永远不会破坏静态视图。
2.使用静态上下文
永远不要将Context作为静态使用,因为该上下文将在应用程序的整个生命周期中都可用,并且不限于特定的活动。
public class MainActivity extends AppCompatActivity {
// this should not be done
private static Button button;
}
3.经常使用代码抽象
开发人员通常会利用abstraction属性的优势,因为它可以提供代码维护和代码灵活性,但是使用abstraction可能会给开发人员带来一些开销,因为使用abstraction需要编写更多的代码,而更多的代码则意味着需要更多的时间来执行代码。空间和更多RAM。因此,只要能避免代码中的抽象,它就是代码,因为它可以减少内存泄漏。
4.未注册的侦听器
当开发人员在其应用程序代码中使用任何类型的侦听器时,开发人员都不应忘记注销该侦听器。
5.未注册的接收者
开发人员很多时候需要在活动中注册本地广播接收器。但是,如果开发者未取消广播接收者的注册,则我们的应用很可能会导致内存泄漏问题,因为接收者会对该活动保持强烈的参考。因此,即使该活动没有用,也将阻止垃圾收集器收集用于垃圾收集的活动,这最终将导致内存泄漏。
Kotlin
// sample kotlin program for broadcast receiver
import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import com.example.myapplication.R
class LocalBroadcastReceiverActivity : Activity() {
private var localBroadcastReceiver: BroadcastReceiver? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
private fun registerBroadCastReceiver() {
localBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Write your code here
}
}
registerReceiver(localBroadcastReceiver, IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"))
}
override fun onStart() {
super.onStart()
// registering the broadcast receiver
registerBroadCastReceiver()
}
override fun onStop() {
super.onStop()
// Broadcast receiver holds the implicit reference of Activity.
// Therefore even if activity is destroy,
// garbage collector will not be able to remove its instance.
if (localBroadcastReceiver != null) {
unregisterReceiver(localBroadcastReceiver)
}
}
}
6.内部类参考
内部类通常由android开发人员在其代码内使用。但是,非静态类将保留父类的隐式引用,这可能导致内存泄漏问题。因此,可以提出两种解决方案来解决此问题:
- 一个可以使内部类静态的
- 如果要传递非静态内部类的引用,则可以使用弱引用来传递它。
检测内存泄漏的工具
众所周知,当无法看到某些东西时,很难修复它,就像内存泄漏一样,也无法看到它,因此很难修复。但是有些工具可以帮助我们检测android应用程序中的内存泄漏并帮助我们对其进行修复。让我们看一些最受欢迎的工具:
1.泄漏金丝雀
Leak Canary是Android中的内存检测库。它是由方形杯子公司开发的。该库具有减少内存泄漏并帮助开发人员减少“ MemoryOutOfError”的独特功能。泄漏金丝雀甚至可以帮助我们通知泄漏实际发生的位置。要使用Leak-Canary,请在build.gradle(应用级文件)中添加以下依赖项。
dependencies {
// debugImplementation because LeakCanary should only run in debug builds.
debugImplementation ‘com.squareup.leakcanary:leakcanary-android:2.4’
}
一旦安装了泄漏金丝雀,它会通过4个步骤自动检测并报告内存泄漏:
- 检测保留的对象。
- 转储堆。
- 分析堆。
- 分类泄漏。
如果想更深入地学习并学习如何泄漏金丝雀,报告内存泄漏可以参考泄漏金丝雀的官方文档。
2. Android Profiler
基本上,这是一个有助于跟踪android中每个应用程序的内存使用情况的工具。它取代了Android 3.0及更高版本中的Android Monitor。 Android Profiler与Android 5.0(API级别21)及更高版本兼容。 Android Profiler根据以下参数实时检测应用程序的性能:
- 电池
- 记忆体(MB)
- CPU使用率(以%为单位)
- 网路费率(上载和接收的速率)
要在android studio中的Android项目中打开android profiler,请执行以下步骤:选择“视图”>“工具Windows”>“ Profiler”>“选择部署目标”,然后选择设备。该应用程序的性能将如下图所示列出:
要了解有关android分析器工作原理的更多信息,请参阅android分析器的官方文档。