android - Toast$TN.mNextView 内存泄漏

标签 android memory-leaks leakcanary

我将泄漏金丝雀添加到我的应用程序中,我发现此内存泄漏:https://i.imgur.com/8nFOoH4.png

我不在我的 MainActivity LinearLayout 或 Toast 上使用,但我有这个泄漏,我不明白为什么以及如何。也许是因为我在 MainActivity 中使用的 fragment 内使用了 toast 和线性布局?

这是我的 MainActivity xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/lost_connection_image_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/fullscreen_exit"/>

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimaryDark"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <de.hdodenhof.circleimageview.CircleImageView
            android:id="@+id/userPhoto"
            android:layout_width="36dp"
            android:layout_height="36dp"
            android:layout_alignParentEnd="true"
            android:layout_gravity="end"
            android:layout_margin="8dp"
            android:background="@android:color/transparent"
            android:src="@drawable/account_default"
            android:visibility="visible"
            tools:layout_editor_absoluteX="312dp"
            tools:layout_editor_absoluteY="4dp"/>

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_margin="8dp"
            app:cardBackgroundColor="@android:color/background_light"
            app:cardCornerRadius="1dp"
            tools:layout_editor_absoluteX="16dp"
            tools:layout_editor_absoluteY="28dp">

            <android.support.constraint.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:focusable="true"
                android:focusableInTouchMode="true">

                <EditText
                    android:id="@+id/search_field"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="8dp"
                    android:layout_marginEnd="8dp"
                    android:layout_marginStart="8dp"
                    android:layout_marginTop="8dp"
                    android:background="@null"

                    android:ems="10"
                    android:hint="@string/search_for"
                    android:imeOptions="actionSearch"
                    android:inputType="text"
                    android:singleLine="true"
                    android:textColorHint="@android:color/darker_gray"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toStartOf="@+id/search"
                    app:layout_constraintStart_toStartOf=" parent"
                    app:layout_constraintTop_toTopOf="parent"/>

                <ImageView
                    android:id="@+id/search"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="8dp"
                    android:layout_marginTop="8dp"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintTop_toTopOf="parent"
                    app:srcCompat="@drawable/search"/>
            </android.support.constraint.ConstraintLayout>

        </android.support.v7.widget.CardView>
    </android.support.v7.widget.Toolbar>


    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        app:layout_constraintBottom_toTopOf="@+id/navigationView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar">

    </FrameLayout>

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/navigationView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimaryDark"
        app:itemIconTint="@color/bottom_nav_selected"
        app:itemTextColor="@color/bottom_nav_selected"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/menu_main"/>
</android.support.constraint.ConstraintLayout>

以及我放入 FrameLayout 的 fragment 之一,其 id 为“container”:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/home_fragment_root"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentBottom="true"
        android:layout_marginStart="0dp"
        android:layout_marginTop="0dp"
        android:layout_marginEnd="0dp"
        android:layout_marginBottom="0dp"
        android:visibility="invisible">

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

            <android.support.constraint.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:focusable="false"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="parent">


                <com.bondpm.bond.customViews.WrapContentViewPager
                    android:id="@+id/viewPager"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:background="@android:color/background_light"
                    android:focusable="true"
                    android:padding="0dp"
                    app:cardBackgroundColor="@android:color/background_light"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintHorizontal_bias="0.0"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent"/>

                <com.rd.PageIndicatorView
                    android:id="@+id/pageIndicatorView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:layout_marginBottom="8dp"
                    app:layout_constraintBottom_toBottomOf="@id/viewPager"
                    app:layout_constraintEnd_toEndOf="@+id/viewPager"
                    app:layout_constraintStart_toStartOf="parent"
                    app:piv_animationType="scale"
                    app:piv_dynamicCount="true"
                    app:piv_interactiveAnimation="true"
                    app:piv_viewPager="@id/viewPager"/>

            </android.support.constraint.ConstraintLayout>

            <android.support.v7.widget.RecyclerView
                android:id="@+id/home_recycler_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:nestedScrollingEnabled="false"
                android:visibility="visible"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/pageIndicatorView"/>


        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:indeterminate="true"/>

</RelativeLayout> 

这里 MainActivity 代码:
class  MainActivity : BaseActivity(), BottomNavigationView.OnNavigationItemSelectedListener, MainActivityView.View {
    private val presenter = MainActivityPresenter()
    private val TAG = this::class.java.simpleName

    private val homeFragment = HomeFragment()
    private val exploreFragment = ExploreFragment()
    private val feedsFragment = FeedsFragment()

    private var currentTabTag = "home"

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.home -> openFragment(homeFragment, "home")
            R.id.explore -> openFragment(exploreFragment, "explore")
            R.id.feeds -> openFragment(feedsFragment, "feeds")
        }

        return true
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        presenter.attachView(this)

        if (savedInstanceState != null || !Utils.isLogined) {
            if (savedInstanceState != null) {
                currentTabTag = savedInstanceState.getString("currentTab")
                if (Utils.userInfo != null && Utils.userInfo?.data?.user?.photo != null) Glide.with(this).load(Utils.userInfo!!.data.user.photo).into(userPhoto)
                else userPhoto.setImageResource(RBase.drawable.account_default)
            }

            userPhoto.setOnClickListener {
                next()
            }

            userInterfaceInit()

        } else presenter.getUserInfo()
    }

    private fun userInterfaceInit() {
        navigationView.setOnNavigationItemSelectedListener(this)
        navigationView.menu.getItem(0).isChecked = true

//        search_field.text = SpannableStringBuilder("")
        search.setOnClickListener{
            if(search_field.text.toString() != "") {
                val intent = Intent(this, SearchActivity::class.java)
                intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
                intent.putExtra("query", search_field.text.toString())
                startActivity(intent)
            }
        }

        search_field.setOnEditorActionListener(TextView.OnEditorActionListener { _, actionId, _ ->
            if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                if(search_field.text.toString() != "") {
                    val intent = Intent(this, SearchActivity::class.java)
                    intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
                    intent.putExtra("query", search_field.text.toString())
                    startActivity(intent)
                }
                return@OnEditorActionListener true
            }
            false
        })

        Log.d(TAG, currentTabTag)

        when (currentTabTag) {
            "home" -> openFragment(homeFragment, "home")
            "explore" -> openFragment(exploreFragment, "explore")
            "feeds" -> openFragment(feedsFragment, "feeds")
        }


        userPhoto.setOnClickListener {
            next()
        }
        setSupportActionBar(toolbar)
        supportActionBar!!.title = ""
    }

    private fun openFragment(fragment: Fragment, tag: String) {
        val transaction = fragmentManager.beginTransaction()
        transaction.replace(R.id.container, fragment, tag)
        currentTabTag = tag
        if (!isFinishing &&!isDestroyed) transaction.commitAllowingStateLoss()
    }

    override fun onSaveInstanceState(outState: Bundle?) {
        super.onSaveInstanceState(outState)
        outState!!.putString("currentTab", currentTabTag)
    }

    override fun showUserInfo() {
        if (Utils.userInfo != null && Utils.userInfo!!.data.user.photo != null) Glide.with(this).load(Utils.userInfo!!.data.user.photo).into(userPhoto)
        else userPhoto.setImageResource(RBase.drawable.account_default)
        userInterfaceInit()
    }

    override fun showMessage(resId: Int) {
        //Toast.makeText(applicationContext, resId, Toast.LENGTH_LONG).show()
    }

    override fun onDestroy() {
        super.onDestroy()
        presenter.detachView()
        presenter.destroy()
    }

最佳答案

看起来你的 toast 比 parent Activity 的生命周期更长。尝试将应用程序用作上下文。就像在您评论的代码中一样:

Toast.makeText(applicationContext, resId, Toast.LENGTH_LONG).show()

关于android - Toast$TN.mNextView 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52890704/

相关文章:

android - 如何从另一个应用程序的通知中获取图像?

Android 联系人选择器 list

C++ char[] 内存泄漏?

java - 一个应用程序中的数据库连接泄漏是否会影响服务器中的其他应用程序?

android - 如何忽略 LeakCanary 中的某些类?

java - Android - 在新选项卡中打开 Firefox Intent url

javascript - node.js - 需要错误导致内存泄漏?

android - 使用 fragment 和导航组件泄漏 nestedscrollView

java - 匿名实现导致内存泄漏

android - FFmpeg 文件未找到异常,没有这样的文件或目录