内存碎片泄漏

问题描述 投票:0回答:1

我正在开发具有单一活动的应用程序。内部有一个主要片段和两个片段,这是代码:

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="viewModel"
            type="com.example.coreproject.presentation.viewModel.MainViewModel" />
    </data>

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <Button
                android:id="@+id/back_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/padding_normal"
                android:onClick="@{viewModel::resetAuth}"
                android:text="Reset authorization" />

            <Button
                android:id="@+id/about_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/padding_normal"
                android:onClick="@{viewModel::goToAbout}"
                android:text="About" />

            <fragment
                class="com.example.services.presentation.view.PopularServiceListFragmentWidget"
                android:id="@+id/widget_popular_services"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/padding_normal"/>

            <fragment
                class="com.example.services.presentation.view.CategoryListFragmentWidget"
                android:id="@+id/widget_categories"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/padding_normal"
                android:layout_marginBottom="@dimen/padding_big"/>

        </LinearLayout>

    </androidx.core.widget.NestedScrollView>

</layout>

我可以从这里转到另一个片段,当我这样做时,会发生内存泄漏。这是堆栈跟踪:

LeakingInstance(referenceKey=c4b8a77a-e8c0-4e6a-937d-d14422c9a616, referenceName=, 
instanceClassName=androidx.core.widget.NestedScrollView, watchDurationMillis=-515750270, 
exclusionStatus=null, leakTrace=
D/LeakCanary: ┬
D/LeakCanary: ├─ android.os.HandlerThread
D/LeakCanary: │    Leaking: NO (it's a GC root)
D/LeakCanary: │    Thread name: 'LeakCanary-Heap-Dump'
D/LeakCanary: │    ↓ thread HandlerThread.contextClassLoader
D/LeakCanary: ├─ dalvik.system.PathClassLoader
D/LeakCanary: │    Leaking: NO (Object[]↓ is not leaking and Classloader never leaking)
D/LeakCanary: │    ↓ PathClassLoader.runtimeInternalObjects
D/LeakCanary: ├─ java.lang.Object[]
D/LeakCanary: │    Leaking: NO (Glide↓ is not leaking)
D/LeakCanary: │    ↓ array Object[].[694]
D/LeakCanary: ├─ com.bumptech.glide.Glide
D/LeakCanary: │    Leaking: NO (Glide↓ is not leaking and a class is never leaking)
D/LeakCanary: │    ↓ static Glide.glide
D/LeakCanary: ├─ com.bumptech.glide.Glide
D/LeakCanary: │    Leaking: NO (ArrayList↓ is not leaking)
D/LeakCanary: │    ↓ Glide.managers
D/LeakCanary: ├─ java.util.ArrayList
D/LeakCanary: │    Leaking: NO (Object[]↓ is not leaking)
D/LeakCanary: │    ↓ ArrayList.elementData
D/LeakCanary: ├─ java.lang.Object[]
D/LeakCanary: │    Leaking: NO (RequestManager↓ is not leaking)
D/LeakCanary: │    ↓ array Object[].[2]
D/LeakCanary: ├─ com.bumptech.glide.RequestManager
D/LeakCanary: │    Leaking: NO (SupportRequestManagerFragment$SupportFragmentRequestManagerTreeNode↓ is not leaking)
D/LeakCanary: │    ↓ RequestManager.treeNode
D/LeakCanary: ├─ com.bumptech.glide.manager.SupportRequestManagerFragment$SupportFragmentRequestManagerTreeNode
D/LeakCanary: │    Leaking: NO (SupportRequestManagerFragment↓ is not leaking)
D/LeakCanary: │    ↓ SupportRequestManagerFragment$SupportFragmentRequestManagerTreeNode.this$0
D/LeakCanary: ├─ com.bumptech.glide.manager.SupportRequestManagerFragment
D/LeakCanary: │    Leaking: NO (MainFragment↓ is not leaking and SupportRequestManagerFragment#mFragmentManager is not null)
D/LeakCanary: │    ↓ SupportRequestManagerFragment.mParentFragment
D/LeakCanary: ├─ com.example.coreproject.presentation.view.MainFragment
D/LeakCanary: │    Leaking: NO (MainFragment#mFragmentManager is not null)
D/LeakCanary: │    ↓ MainFragment.binding
D/LeakCanary: │                   ~~~~~~~
D/LeakCanary: ├─ com.example.coreproject.databinding.FragmentMainBindingImpl
D/LeakCanary: │    Leaking: UNKNOWN
D/LeakCanary: │    ↓ FragmentMainBindingImpl.mRoot
D/LeakCanary: │                              ~~~~~
D/LeakCanary: ╰→ androidx.core.widget.NestedScrollView
D/LeakCanary: ​     Leaking: YES (RefWatcher was watching this)
D/LeakCanary: , retainedHeapSize=null)])

除了主片段,如果切换到内置片段和所有后续片段,它们也会泄漏,但是如果返回到主要片段,则泄漏将消失。我不知道该如何解决。任何帮助表示赞赏。

android android-fragments memory-leaks leakcanary
1个回答
0
投票

基于泄漏跟踪,我们可以看到MainFragment没有泄漏,但是它有一个binding字段,该字段引用了FragmentMainBindingImpl,而FragmentMainBindingImpl本身引用了一个分离的视图。该视图是MainFragment的视图,这意味着调用了Fragment.onDestroyView()。调用Fragment.onDestroyView()时,片段应放弃对视图的引用,即binding应设置为null。

© www.soinside.com 2019 - 2024. All rights reserved.