使用 RecyclerView 时 Android YouTube API 内存泄漏

标签 android android-youtube-api leakcanary

我有一个包含图片列表和 YouTube 缩略图的 RecyclerView。如果用户点击 YouTube 缩略图,它会打开一个新 Activity ,在上半部分显示嵌入的 YouTube 视频(使用 YouTube Android Player API fragment )并在下半部分。

我的问题是,无论我如何尝试实现 YouTube Android Player API、Android Studio & Leak Canary当我按下后退按钮返回到我的 RecyclerView 时,将始终显示它正在泄漏。我对 LeakCanary 和整个 Android 开发相当陌生。如果我可以提供有关泄漏的更多详细信息,请告诉我,我将编辑这篇文章以包含它。

我已经尝试了很多方法来让它工作,YouTube 建议的两种方式,YouTubePlayerFragmentYouTubePlayerView。在这一点上,我不知道还能做什么。这仅在我使用 YouTube API 时发生,如果我只显示图片,我的 Activity 不会泄漏。非常感谢任何帮助,我已经准备好拔掉头发了。

LeakCanary

YouTubePlayerActivity 是我的类,它不在 YouTube API 中。此外,展开任何 LeakCanary 跟踪都不会泄露任何细节。

Youtube Leak Canary

回收 View

这是我的 onBindViewHolder(),我在其中设置了 onClickListener(),它会打开我的 YouTubePlayerActivity

mImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Context context = v.getContext();

                Intent youtubeIntent = new Intent(context,YouTubePlayerActivity.class);

                Bundle bundle = new Bundle();

                bundle.putString("foo", object.getUrl());
                bundle.putString("foo1", object.getDescription());

                youtubeIntent.putExtras(bundle);

                context.startActivity(youtubeIntent, bundle);

               }
        });

YouTubePlayerActivity.class

显示我的 YouTube 播放器的类的精简版。这是我尝试实现它的许多方法中的最后一种。但是,无论我如何尝试实现它,泄漏都存在。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.detail_main_youtube);

    Bundle bundle = getIntent().getExtras();

    url = bundle.getString("foo");
    description = bundle.getString("foo1");


    TextView detailDescription = (TextView) findViewById(R.id.txt_detail_description_youtube);
detailDescription.setText(description);

    myFragment = PlayerYouTubeFrag.newInstance("Some random YouTube Id");
    myTransaction = getFragmentManager().beginTransaction();
    myTransaction.addToBackStack(null);
    myTransaction.replace(R.id.youtube_fragment, myFragment).commit();

}

PlayerYouTubeFrag

public class PlayerYouTubeFrag extends YouTubePlayerFragment {

private YouTubePlayer activePlayer;

public static PlayerYouTubeFrag newInstance(String youTubeId) {

    PlayerYouTubeFrag playerYouTubeFrag = new PlayerYouTubeFrag();

    Bundle bundle = new Bundle();
    bundle.putString("youTubeId", youTubeId);

    playerYouTubeFrag.setArguments(bundle);
    playerYouTubeFrag.init();
    return playerYouTubeFrag;
}

private void init() {

    initialize(Config.YOUTUBE_API_KEY, new YouTubePlayer.OnInitializedListener() {

        @Override
        public void onInitializationFailure(YouTubePlayer.Provider arg0, YouTubeInitializationResult arg1) {
        }

        @Override
        public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer player, boolean wasRestored) {
            activePlayer = player;
            activePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.DEFAULT);
            if (!wasRestored) {
                activePlayer.loadVideo(getArguments().getString("youTubeId"), 0);

            }
        }
    });
}

}

XML 布局

这是我的 YouTubePlayerActivity 的 xml Frame Layout,它被 Fragment 替换了。

<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/detail_main_youtube"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/backgroundColor">


    <FrameLayout
        android:id="@+id/youtube_fragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:visibility="visible" />

    <ScrollView
        android:id="@+id/scroll_view_youtube"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

            <TextView
                android:id="@+id/txt_detail_description_youtube"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="20dp"
                android:layout_marginLeft="15dp"
                android:layout_marginRight="15dp"
                android:layout_marginTop="20dp"
                android:background="@color/backgroundColor"
                android:lineSpacingExtra="5dp"
                android:textColor="@color/darkTextColor"
                android:textSize="15sp" />

    </ScrollView>
</LinearLayout>

最佳答案

尝试在您的 PlayerYouTubeFrag 代码中添加这些行:

@Override
public void onDetach() {
    super.onDetach();
    activePlayer.release();
    activePlayer = null;
}

关于使用 RecyclerView 时 Android YouTube API 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42861439/

相关文章:

android - Youtube 数据 API v3 在创建发布 apk 时不上传视频

android - MapView保持上下文导致内存泄漏

android - 将多个图像 URL 共享给其他应用程序

android - 无法删除 CardView 项目之间的额外空间 - 可滚动的 RecyclerView

android - 刷机前自定义 Android ROM 应用程序数据

android - Youtube api Apache 2.0 许可证

java - 使用 ValueAnimator 将 View 缩放到另一个 View 的大小

android - Android | YouTube在线直播

java - MediaControllerCompat 内存泄漏

android - 如何使用新的 AndroidProfiler 处理内存泄漏