这个Runnable类会导致内存泄漏吗?

时间:2019-02-21 18:36:02

标签: android multithreading kotlin memory-leaks runnable

我创建了一个类,并使用Runnable对其进行了扩展。该类应该在后台执行操作并将结果发布到UI线程上。但是,我正在使用此Runnable类的变量属于outter类(Parent类)。示例:

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

        }
    }

2 个答案:

答案 0 :(得分:1)

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

要解决此问题,通常建议坚持使用WeakReference对象,从中需要包含类的数据,或者坚持使用WeakReference到活动/片段(如果您是)直接访问活动/片段(就像您在getActivity()中使用Runnable一样)。

答案 1 :(得分:0)

您的代码似乎没有泄漏内存。但是,确保它的最佳方法是对其进行测试。运行它多次,然后查看内存是否增加。有什么理由让您认为这是泄漏吗?

换句话说,您可能应该避免拆开所有内容并保留可选内容(这意味着使用?而非!!)。