这个 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 比容器对象长,它们可能会泄漏内存。 在您的情况下,FragmentRunnable 完成之前不会进行 GC,因为内部 class 持有对包含 Fragment.[=17= 的隐式引用]

为了解决这个问题,通常建议将 WeakReference 保留到您需要来自包含 class 的数据的对象或 WeakReference 到 Activity/Fragment,如果您直接访问 Activity/Fragment(就像您在 Runnable 中访问 getActivity())。