dependencies {
// debugImplementation 是因为 LeakCanary 应该只工作在 debug 编译环境.
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
}
LeakCanary
即可。LeakCanary xxx D LeakCanary is running and ready to detect memory leaks.
如果一个对象被持久地引用,并存储在静态变量中,那么即使Activity或Fragment已经被销毁,该对象仍然存在于内存中,从而导致内存泄露。为了避免这种情况,应该避免在静态变量中持有Activity或Fragment的引用。
class MySingleton {
companion object {
var instance: Activity? = null
}
}
// 在Activity中持有了MySingleton的引用
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MySingleton.instance = this
}
}
改:
class MySingleton {
companion object {
private var instance: WeakReference<MainActivity>? = null
fun getInstance(): MainActivity? {
return instance?.get()
}
fun setInstance(activity: MainActivity) {
instance = WeakReference(activity)
}
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MySingleton.setInstance(this)
}
}
非静态内部类默认会持有外部类的引用,如果非静态内部类的实例被持久地引用,那么外部类也无法被GC回收,从而导致内存泄露。可以将非静态内部类声明为静态内部类,或者使用弱引用(WeakReference)来解决这个问题。
class OuterClass {
// 非静态内部类,默认持有外部类的引用
inner class InnerClass {
fun doSomething() {
// 执行一些操作
}
}
}
// 在Activity中持有了InnerClass的引用
class MainActivity : AppCompatActivity() {
private val innerClass: OuterClass.InnerClass = OuterClass().InnerClass()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
innerClass.doSomething()
}
}
改:
class OuterClass {
// 非静态内部类,默认持有外部类的引用
static inner class InnerClass {
fun doSomething() {
// 执行一些操作
}
}
}
class MainActivity : AppCompatActivity() {
private val innerClass: OuterClass.InnerClass? = OuterClass().InnerClass()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
innerClass?.doSomething()
}
}
如果在Activity或Fragment中注册了监听器(如广播接收器、触摸事件监听器等),在不再需要监听器时忘记取消注册,就会导致内存泄露。为了避免这种情况,应该在不需要监听器时及时取消注册。
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
// 接收到广播后执行一些操作
}
}
// 在Activity中注册了广播接收器,但没有在合适的时机取消注册
class MainActivity : AppCompatActivity() {
private val receiver: MyBroadcastReceiver = MyBroadcastReceiver()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val filter = IntentFilter()
filter.addAction("com.example.ACTION")
registerReceiver(receiver, filter)
}
}
改:
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
// 接收到广播后执行一些操作
}
}
class MainActivity : AppCompatActivity() {
private var receiver: MyBroadcastReceiver? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val filter = IntentFilter()
filter.addAction("com.example.ACTION")
receiver = MyBroadcastReceiver()
registerReceiver(receiver, filter)
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(receiver)
receiver = null
}
}
在使用一些需要手动关闭的资源(如数据库连接、文件输入输出流等)时,如果忘记关闭这些资源,就会导致内存泄露。为了避免这种情况,应该在不再需要资源时及时关闭它们。
class FileOperation {
fun readFile() {
val file = File("example.txt")
val inputStream = FileInputStream(file)
// 读取文件内容
// ...
// 忘记关闭文件输入流
}
}
// 在Activity中执行文件读取操作,但忘记关闭文件输入流
class MainActivity : AppCompatActivity() {
private val fileOperation: FileOperation = FileOperation()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fileOperation.readFile()
}
}
改:
class FileOperation {
fun readFile() {
val file = File("example.txt")
var inputStream: FileInputStream? = null
try {
inputStream = FileInputStream(file)
// 读取文件内容
// ...
} catch (e: IOException) {
e.printStackTrace()
} finally {
inputStream?.close()
}
}
}
class MainActivity : AppCompatActivity() {
private val fileOperation: FileOperation = FileOperation()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fileOperation.readFile()
}
}
如果在Activity或Fragment中启动了异步任务(如AsyncTask、线程等),并且在Activity或Fragment被销毁时没有取消这些任务,就会导致内存泄露。为了避免这种情况,应该在Activity或Fragment的生命周期方法中及时取消异步任务。
class MyAsyncTask : AsyncTask<Void, Void, String>() {
override fun doInBackground(vararg params: Void?): String {
// 执行一些耗时操作
return "result"
}
}
// 在Activity中启动异步任务,但没有在合适的时机取消任务
class MainActivity : AppCompatActivity() {
private var asyncTask: MyAsyncTask? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
asyncTask = MyAsyncTask().execute()
}
}
改:
class MyAsyncTask(private val activity: WeakReference<MainActivity>) :
AsyncTask<Void, Void, String>() {
override fun doInBackground(vararg params: Void?): String {
// 执行一些耗时操作
return "result"
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
val activity = activity.get()
if (activity != null && !activity.isFinishing) {
// 处理任务结果
}
}
}
class MainActivity : AppCompatActivity() {
private var asyncTask: MyAsyncTask? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
asyncTask = MyAsyncTask(WeakReference(this)).execute()
}
override fun onDestroy() {
super.onDestroy()
asyncTask?.cancel(true)
asyncTask = null
}
}
Thank you for your reading, best regards!