SharedElement和自定义EnterTransition导致内存泄漏

2023-11-26

拥有共享元素动画和自定义输入动画会导致活动泄漏。

知道可能是什么原因吗?

09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * com.feeln.android.activity.MovieDetailActivity has leaked: 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * GC ROOT android.app.ActivityThread$ApplicationThread.this$0 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references android.app.ActivityThread.mActivities 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references android.util.ArrayMap.mArray 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references array java.lang.Object[].[1] 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references android.app.ActivityThread$ActivityClientRecord.activity 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references com.feeln.android.activity.MovieDetailActivity.mActivityTransitionState 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references android.app.ActivityTransitionState.mEnterTransitionCoordinator 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references android.app.EnterTransitionCoordinator.mEnterViewsTransition 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references android.transition.TransitionSet.mParent 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references android.transition.TransitionSet.mListeners 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references java.util.ArrayList.array 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references array java.lang.Object[].[1] 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references android.transition.TransitionManager$MultiListener$1.val$runningTransitions (anonymous class extends android.transition.Transition$TransitionListenerAdapter) 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references android.util.ArrayMap.mArray 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references array java.lang.Object[].[2] 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * references com.android.internal.policy.impl.PhoneWindow$DecorView.mContext 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * leaks com.feeln.android.activity.MovieDetailActivity instance 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ [ 09-21 16:19:31.007 28269:31066 D/LeakCanary ] * Reference Key: af2b6234-297e-4bab-96e9-02f1c4bca171 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * Device: LGE google Nexus 5 hammerhead 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * Android Version: 5.1.1 API: 22 LeakCanary: 1.3.1 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ * Durations: watch=6785ms, gc=262ms, heap dump=8553ms, analysis=33741ms 09-21 16:19:31.007 28269-31066/com.sample.android D/LeakCanary﹕ [ 09-21 16:19:31.007 28269:31066 D/LeakCanary ]

要重现,您需要有一个大的共享图像动画以及一个自定义 EnterAnimation 和 setEnterSharedElementCallback 。所有这些都来自支持库。

这是我设置 EnterTransition 的方法:

private SharedElementCallback mCallback = new SharedElementCallback() {
    @Override
    public void onSharedElementStart(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
        {
            if(sharedElements.size()>0)
                getWindow().setEnterTransition(makeEnterTransition(getWindow().getEnterTransition(), getSharedElement(sharedElements)));
        }
    }


    private View getSharedElement(List<View> sharedElements)
    {
        for (final View view : sharedElements)
        {
            if (view instanceof ImageView)
            {
                return view;
            }
        }
        return null;
    }
};

泄漏案例在于TransitionManager.sRunningTransitions其中每个DecorView添加并且从不删除。DecorView有他的链接Activity's Context。因为sRunningTransitions是静态字段,它具有永久的引用链Activity,永远不会被 GC 收集。

我不知道为什么 TransitionManager.Running Transitions 需要,但如果你删除Activity's DecorView从此,你的问题就会得到解决。下面的代码就是例子,怎么做。在您的活动课中:

@Override
protected void onDestroy() {
    super.onDestroy();
    removeActivityFromTransitionManager(Activity activity);
}

private static void removeActivityFromTransitionManager(Activity activity) {
    if (Build.VERSION.SDK_INT < 21) {
        return;
    }
    Class transitionManagerClass = TransitionManager.class;
    try {
        Field runningTransitionsField = transitionManagerClass.getDeclaredField("sRunningTransitions");
            runningTransitionsField.setAccessible(true);
        //noinspection unchecked
        ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>> runningTransitions
                = (ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>)
                runningTransitionsField.get(transitionManagerClass);
        if (runningTransitions.get() == null || runningTransitions.get().get() == null) {
            return;
        }
        ArrayMap map = runningTransitions.get().get();
        View decorView = activity.getWindow().getDecorView();
        if (map.containsKey(decorView)) {
            map.remove(decorView);
        }
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SharedElement和自定义EnterTransition导致内存泄漏 的相关文章

  • C# 与 JAVA 接口实例

    我不知道该如何回答我的问题 它是关于Android可以实例化接口的 我正在尝试用 C 来做 现在我非常确定 Java 和 C 的规则是不能创建抽象和接口的实例 但我很想知道Android是如何做到这一点的 在 Android 中你可以这样做
  • 简单对话框中的 ViewPager

    我想在对话框中使用 ViewPager 但失败了 这是所有代码 对话框中显示两个片段 Layouts main xml
  • 从SQLite列中获取所有数字字符串并进行总和计算

    我是 Android 和 SQLite 的新手 我在 SQLite 中有一个只有数字的 AMOUNT 列 我可以在 ListView 中显示它 但我无法找到任何我理解的方法来将它们全部添加并显示在 TextView 中 这是数据库助手 im
  • 当模态打开时,如何将焦点设置在模态内的第一个 TouchableHighlight 组件(或另一个组件,例如由 ref 给出)上?

    当模式打开时 如何将焦点设置到模式内的第一个 或任何给定的 TouchableHighlight 组件 我正在使用方向键 键盘 电视遥控器 让我们使用react native文档模式示例的片段
  • Fused Location Provider 是不错的选择吗?

    我正在开发一个应用程序 我想在其中使用融合位置提供程序 但我有一些疑问 还有几个问题 当 GPS 关闭并且我将优先级设置为 HIGH 时 是否意味着 GPS 会自动打开 我可以根据需要将 UpdateLocation 设置为具有高优先级的
  • WebView 与 Chrome 自定义选项卡

    我正在构建一个应用程序 在详细活动中我必须显示一个网页 我本来打算使用 WebView 但后来我看到了 Chrome Custom Tab 你们认为最好实施什么 为什么 如果您只想显示某个页面 那么我建议您使用 chrome 自定义选项卡
  • 如何将音频 Mediastore 持续时间转换为分钟和秒?

    我正在使用音频播放器教程androidhive info https www androidhive info 2012 03 android building audio player tutorial 在 SongsManager ja
  • 带有 ListTiles 和按钮行的 Flutter 下拉菜单

    我正在尝试构建一个自定义下拉菜单 如下所示 我已经成功地实现了ListTiles and Row of Buttons没有下拉菜单 但我不确定如何将所有内容嵌套在下拉菜单类中 这是我到目前为止所得到的 class HomePage exte
  • Android 拖放 ACTION_DRAG_ENDED 未触发

    我真的很花时间解决这个问题 到目前为止找不到任何有相关经验的朋友 这是我发布第一个应用程序之前的最后一个功能 所以在结局即将到来的情况下陷入困境让我发疯 如果我将对象放在可接受的区域中 我的拖放效果会非常好 但是 如果拖放到其他地方 我不会
  • MediaStyle 通知未响应 RemoteControl 事件。

    我们正在将正在进行的播放通知迁移到 Lollipop 中引入的 MediaStyle 通知 RemoteControlClient 似乎已被弃用 并且 MediaStyle 通知不处理媒体按钮事件 例如通过耳机远程暂停 播放 有人得到这个工
  • 直接在应用程序中评价 Google Play 应用程序 [重复]

    这个问题在这里已经有答案了 我需要在我的 Android 应用程序中设置费率选项 我找到了这个link http www androidsnippets com prompt engaged users to rate your app i
  • 长按 HOME 按钮菜单隐藏 Android 应用程序

    我想从 且仅从 完成后长时间按住 HOME 按钮时出现的菜单中隐藏我的 Android 应用程序 有没有办法做到这一点 以编程方式调用 finish 并不能解决问题 有很多关于从启动器和任务管理器隐藏应用程序的线程 但这不是我想要的 我只是
  • Gradle创建多项目Jar

    因此 从 Gradle 和 Android Studio 诞生之初起 我就一直在使用它们 然而 我发现自己用头撞墙的次数有时远远超过了它的价值 我花了一天半的时间试图解决我目前的困境 在我工作的地方 我们使用很多共享库项目 这意味着与 Gr
  • SQLiteConstraintException:错误代码19:约束失败——Android错误

    我已经看到了一些与此相关的其他问题 但没有一个答案似乎真正适用于我的代码 当我尝试插入数据库时 出现 SQLiteConstraintException 错误代码 19 约束失败 错误 这是插入操作的代码 db insert 现在返回 1
  • 如何修补更新 Android Studio (0.80 -> 0.81)?

    我安装了 Android Studio Beta v0 8 0 并下载了 v0 8 1 因为 IDE 不会自动下载 v0 80 并使用新版本修补 Android Studio 的预览系列自动做到了这一点 从他们的网页 http tools
  • 对话框片段中的 onActivityResult

    我正在从对话框片段中拍照 我还需要类似的东西startActivityForResult takePictureIntent actionCode Override public void onActivityResult int requ
  • 数字时钟不改变时间

    我正在开发一个数字时钟小部件 我写了代码 但它没有更新时间 我没有使用任何服务并在模拟器中运行 我的代码如下 public class ExampleAppWidgetProvider extends AppWidgetProvider D
  • Android - 按下后退按钮时停止 AsyncTask 并返回到上一个 Activity

    我有一个 AsyncTask 我希望它在按下后退按钮时停止执行 我还希望应用程序返回到之前显示的 Activity 看来我已经成功停止了任务 但应用程序没有返回到之前的活动 有任何想法吗 这是我的代码的摘录 private class My
  • Jetpack 中的波浪框组成

    有没有办法用Canvas制作一个顶部有波浪形的盒子 我想知道这个效果是否可以直接用Canvas来实现 不需要有滚动动画 不太清楚你为什么在谈论Canvas 要裁剪这样的视图 您可以使用自定义Shape并将其应用到您的视图中Modifier
  • 在edittext android中插入imageview

    我想将 imageview 放在 edittext 中 可能吗 我检查了 evernote 应用程序 它能够将照片放在编辑文本部分 我想让我的应用程序完全相同 我如何才能将从图库中选择的图像视图放入编辑文本中 我首先尝试将 imagevie

随机推荐