首页 > 解决方案 > 这个 Runnable 类会导致内存泄漏吗?

问题描述

我创建了一个类并用Runnable. 这个类应该在后台进行操作并在 UI 线程上发布结果。但是,我使用这个Runnable类的变量属于外部类(父类)。例子:

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类成员变量。这会导致内存泄漏吗?如果是怎么避免呢?

这是我写的实际代码:

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
                }
            })

        }
    }

标签: androidmultithreadingkotlinmemory-leaksrunnable

解决方案


如果非静态内部类比容器对象寿命长,它们可能会泄漏内存。在您的情况下,Fragment在完成之前不会进行 GC,Runnable因为内部类持有对包含的隐式引用Fragment

为了解决这个问题,如果您直接WeakReference访问WeakReferenceActivity/Fragment(就像您getActivity()Runnable)。


推荐阅读