这个 Runnable class 会导致内存泄漏吗?
Could this Runnable class cause memory leaks?
我创建了一个 class 并用 Runnable
扩展了它。此 class 应该在后台执行操作,并且 post 在 UI 线程上产生结果。但是,我使用的变量Runnable
class 属于outter class(Parent class)。示例:
Class MainFragment {
onStart() {
val runnable = BackgroundRunnable()
Thread(runnable).start()
}
private inner class BackgroundRunnable: Runnable {
onRun() {
//using MainFragment`s member variables here
//performing background ops that can take more than 48ms
}
getActivity().runOnUiThread(object : Runnable {
override fun run() {
//notfiyDataSetChanged()
}
}
}
}
从上面的示例代码可以看出,我正在使用 inner
来访问 MainFragment
class 成员变量。这会导致内存泄漏?如果是,如何避免?
下面是我写的实际代码:
private inner class BackgroundRunnable : Runnable {
override fun run() {
list!!.clear()
listItems!!.clear()
list = dbHandler!!.readAllNotes()
for (noteReader in list!!.iterator()) {
val note = UserNotes()
note.noteTitle = noteReader.noteTitle
note.noteText = noteReader.noteText
note.noteID = noteReader.noteID
note.noteColor = noteReader.noteColor
note.noteEncrypted = noteReader.noteEncrypted
note.noteCheckList = noteReader.noteCheckList
note.noteDate = noteReader.noteDate
note.noteTempDel = noteReader.noteTempDel
note.noteArchived = noteReader.noteArchived
note.noteReminderID = noteReader.noteReminderID
note.noteReminderText = noteReader.noteReminderText
listItems!!.add(note)
}
activity!!.runOnUiThread(object : Runnable {
override fun run() {
adapter!!.notifyDataSetChanged()
return
}
})
}
}
使用弱引用
private class BackgroundRunnable internal constructor(context: NotesFrag) : Runnable {
private val weakReference = WeakReference(context)
override fun run() {
val parentClass = weakReference.get()
parentClass!!.list!!.clear()
parentClass.listItems!!.clear()
parentClass.list = parentClass.dbHandler!!.readAllNotes()
for (noteReader in parentClass.list!!.iterator()) {
val note = UserNotes()
note.noteTitle = noteReader.noteTitle
note.noteText = noteReader.noteText
note.noteID = noteReader.noteID
note.noteColor = noteReader.noteColor
note.noteEncrypted = noteReader.noteEncrypted
note.noteCheckList = noteReader.noteCheckList
note.noteDate = noteReader.noteDate
note.noteTempDel = noteReader.noteTempDel
note.noteArchived = noteReader.noteArchived
note.noteReminderID = noteReader.noteReminderID
note.noteReminderText = noteReader.noteReminderText
parentClass.listItems!!.add(note)
}
parentClass.activity!!.runOnUiThread(object : Runnable {
override fun run() {
parentClass.adapter!!.notifyDataSetChanged()
return
}
})
}
}
您的代码似乎没有泄漏内存。但确定它的最好方法是对其进行测试。 运行 多看几次,看内存有没有增加。有什么理由让你认为它在泄漏吗?
换句话说,您可能应该避免展开所有内容并保留可选项(意思是使用 ?
而不是 !!
)。
如果非静态内部 classes 比容器对象长,它们可能会泄漏内存。
在您的情况下,Fragment
在 Runnable
完成之前不会进行 GC,因为内部 class 持有对包含 Fragment
.[=17= 的隐式引用]
为了解决这个问题,通常建议将 WeakReference
保留到您需要来自包含 class 的数据的对象或 WeakReference
到 Activity/Fragment,如果您直接访问 Activity/Fragment(就像您在 Runnable
中访问 getActivity()
)。
我创建了一个 class 并用 Runnable
扩展了它。此 class 应该在后台执行操作,并且 post 在 UI 线程上产生结果。但是,我使用的变量Runnable
class 属于outter class(Parent class)。示例:
Class MainFragment {
onStart() {
val runnable = BackgroundRunnable()
Thread(runnable).start()
}
private inner class BackgroundRunnable: Runnable {
onRun() {
//using MainFragment`s member variables here
//performing background ops that can take more than 48ms
}
getActivity().runOnUiThread(object : Runnable {
override fun run() {
//notfiyDataSetChanged()
}
}
}
}
从上面的示例代码可以看出,我正在使用 inner
来访问 MainFragment
class 成员变量。这会导致内存泄漏?如果是,如何避免?
下面是我写的实际代码:
private inner class BackgroundRunnable : Runnable {
override fun run() {
list!!.clear()
listItems!!.clear()
list = dbHandler!!.readAllNotes()
for (noteReader in list!!.iterator()) {
val note = UserNotes()
note.noteTitle = noteReader.noteTitle
note.noteText = noteReader.noteText
note.noteID = noteReader.noteID
note.noteColor = noteReader.noteColor
note.noteEncrypted = noteReader.noteEncrypted
note.noteCheckList = noteReader.noteCheckList
note.noteDate = noteReader.noteDate
note.noteTempDel = noteReader.noteTempDel
note.noteArchived = noteReader.noteArchived
note.noteReminderID = noteReader.noteReminderID
note.noteReminderText = noteReader.noteReminderText
listItems!!.add(note)
}
activity!!.runOnUiThread(object : Runnable {
override fun run() {
adapter!!.notifyDataSetChanged()
return
}
})
}
}
使用弱引用
private class BackgroundRunnable internal constructor(context: NotesFrag) : Runnable {
private val weakReference = WeakReference(context)
override fun run() {
val parentClass = weakReference.get()
parentClass!!.list!!.clear()
parentClass.listItems!!.clear()
parentClass.list = parentClass.dbHandler!!.readAllNotes()
for (noteReader in parentClass.list!!.iterator()) {
val note = UserNotes()
note.noteTitle = noteReader.noteTitle
note.noteText = noteReader.noteText
note.noteID = noteReader.noteID
note.noteColor = noteReader.noteColor
note.noteEncrypted = noteReader.noteEncrypted
note.noteCheckList = noteReader.noteCheckList
note.noteDate = noteReader.noteDate
note.noteTempDel = noteReader.noteTempDel
note.noteArchived = noteReader.noteArchived
note.noteReminderID = noteReader.noteReminderID
note.noteReminderText = noteReader.noteReminderText
parentClass.listItems!!.add(note)
}
parentClass.activity!!.runOnUiThread(object : Runnable {
override fun run() {
parentClass.adapter!!.notifyDataSetChanged()
return
}
})
}
}
您的代码似乎没有泄漏内存。但确定它的最好方法是对其进行测试。 运行 多看几次,看内存有没有增加。有什么理由让你认为它在泄漏吗?
换句话说,您可能应该避免展开所有内容并保留可选项(意思是使用 ?
而不是 !!
)。
如果非静态内部 classes 比容器对象长,它们可能会泄漏内存。
在您的情况下,Fragment
在 Runnable
完成之前不会进行 GC,因为内部 class 持有对包含 Fragment
.[=17= 的隐式引用]
为了解决这个问题,通常建议将 WeakReference
保留到您需要来自包含 class 的数据的对象或 WeakReference
到 Activity/Fragment,如果您直接访问 Activity/Fragment(就像您在 Runnable
中访问 getActivity()
)。