Может ли этот класс Runnable вызвать утечки памяти? - PullRequest
0 голосов
/ 21 февраля 2019

Я создал класс и расширил его с помощью Runnable.Этот класс должен выполнять операции в фоновом режиме и публиковать результаты в потоке пользовательского интерфейса.Тем не менее, переменные, которые я использую этот класс 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
                }
            })

        }
    }

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Нестатические внутренние классы могут пропускать память, если они переживают контейнерный объект.В вашем случае Fragment не получит GC'-код до тех пор, пока Runnable не будет завершен, поскольку внутренний класс содержит неявную ссылку на содержащий Fragment.

. Чтобы решить эту проблему, обычно рекомендуетсяудерживать WeakReference объекта, от которого вам потребуются данные из содержащего класса, или WeakReference действия / фрагмента, если вы обращаетесь к действию / фрагменту напрямую (как вы делаете с getActivity() вRunnable).

0 голосов
/ 21 февраля 2019

Ваш код, похоже, не пропускает память.Но лучший способ убедиться в этом - это проверить.Запустите его много раз и посмотрите, увеличивается ли память.Есть ли какая-либо причина, заставляющая вас думать, что это утечка?

В другой заметке вам, вероятно, следует избегать распаковки всего содержимого и сохранять вместо этого дополнительные параметры (то есть использовать ? вместо !!).

...