Утечка памяти при привязке данных - PullRequest
1 голос
/ 24 января 2020

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

Я использовал

  • Привязка данных
  • Навигация
  • Жизненный цикл
  • Материал пользовательского интерфейса
┬───
│ GC Root: System class
│
├─ androidx.databinding.ViewDataBinding class
│    Leaking: NO (a class is never leaking)
│    ↓ static ViewDataBinding.sReferenceQueue
│                             ~~~~~~~~~~~~~~~
├─ java.lang.ref.ReferenceQueue instance
│    Leaking: UNKNOWN
│    ↓ ReferenceQueue.head
│                     ~~~~
├─ androidx.databinding.ViewDataBinding$WeakListener instance
│    Leaking: UNKNOWN
│    ↓ ViewDataBinding$WeakListener.mObservable
│                                   ~~~~~~~~~~~
├─ androidx.databinding.ViewDataBinding$LiveDataListener instance
│    Leaking: UNKNOWN
│    ↓ ViewDataBinding$LiveDataListener.mLifecycleOwner
│                                       ~~~~~~~~~~~~~~~
╰→ com.norm.news.ui.source.NewsSourceFragment instance
​     Leaking: YES (ObjectWatcher was watching this because com.norm.news.ui.source.NewsSourceFragment received Fragment#onDestroy() callback and Fragment#mFragmentManager is null)
​     key = 55b68d7d-56bb-46ff-ad17-e29f01b6a808
​     watchDurationMillis = 5207
​     retainedDurationMillis = 139
​     key = 2fc4bd04-641e-4bea-8e13-71650f6e2a25

METADATA

Build.VERSION.SDK_INT: 24
Build.MANUFACTURER: samsung
LeakCanary version: 2.1
App process name: com.norm.news.debug
Analysis duration: 12283 ms

Вот фрагмент кода в моем фрагменте.

На этот код ссылаются из Android Kotlin Основы 05.3: Привязка данных с ViewModel и LiveData

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding: FragmentNewsSourceBinding = DataBindingUtil.inflate(
            inflater,
            R.layout.fragment_news_source,
            container,
            false
        )
        // Specify the current activity as the lifecycle owner of the binding.
        // This is necessary so that the binding can observe LiveData updates.
        binding.lifecycleOwner = this

        val application = requireNotNull(this.activity).application
        val viewModelFactory = NewsSourceViewModelFactory(application)
        val newsSourceViewModel =
            ViewModelProviders.of(this, viewModelFactory).get(NewsSourceViewModel::class.java)
        binding.newsSourceViewModel = newsSourceViewModel

        binding.rvSourceLists.adapter = NewsSourceAdapter(NewsSourceAdapter.OnClickListener {
            newsSourceViewModel.displayNewsSourceDetails(it)
        })

        newsSourceViewModel.navigateToSelectedItem.observe(viewLifecycleOwner, Observer {
            if (it != null) {
                this.findNavController()
                    .navigate(NewsSourceFragmentDirections.actionNewsSourceFragmentToNewsFragment(it.id))
                newsSourceViewModel.displayNewsSourceDetailsComplete()
            }
        })

        return binding.root
    }

1 Ответ

3 голосов
/ 25 января 2020

Это похоже на ошибку в библиотеке привязки данных, основанную на чтении информации об утечке и источниках. Я не уверен, что это вызвало.

Существует справочная очередь, экземпляры WeakListener добавляются в нее, когда экземпляр их слабого ref слабо доступен. Итак, мы знаем, что это состояние слушателя в этом случае. Слабые очереди WeakRefs будут оставаться там до тех пор, пока очередь не будет обработана путем использования кода (здесь это библиотека привязки данных), что обычно не является проблемой, поскольку ref имеет значение null. Однако здесь у слабой ссылки есть mObservable поля, которые заканчиваются утечкой владельца жизненного цикла, который является разрушенным фрагментом. Это прекратит утечку, когда следующая очередь ссылок будет обработана, хотя пока неясно, когда это произойдет.

Так что это похоже на недостаток дизайна / ошибку в том, как библиотека привязки данных обрабатывает слабые ссылки.

Вам, вероятно, следует сообщить об ошибке в этот проект с дополнительными подробностями, такими как номер версии lib. Также может помочь предоставление дампа кучи (легко распространяемого из утечки в канале).

...