Android:DetailActivity泄露了ServiceConnection

时间:2016-06-14 14:26:38

标签: android android-fragments memory-leaks android-youtube-api

我有一个ViewPager,它由Fragment列表动态填充。所有这些Fragment都有RecyclerView由多种类型的元素组成(每个ItemView不同于另一个,并且无法知道哪个类型的视图位于哪个位置) 。要填充此RecyclerView,我们使用多种相应类型的ViewHolders。其中一个是YoutubeHolder,应该打开一个YoutubeStandalonePlayer实例。这是我的问题:每当方向发生变化或按下Fragment YoutubeHolder上的后退按钮时,我都会收到DetailActivity has leaked ServiceConnection com.google.android.youtube.player.internal.r$e@1ece5fa2 that was originally bound here的异常。如果我在Fragment之间滑动,也会发生这种情况。现在,它并不像我没有发布YoutubeThumbnailLoader来电中获得的onInitializationSuccess一样。我已经在StackOverflow上阅读了很多关于此的问题,但似乎没有任何帮助我!

以下是我YoutubeHolder的代码:

public class ElementYoutubeHolder extends BaseElementHolder implements YouTubeThumbnailView.OnInitializedListener {

YouTubeThumbnailView thumbView;
YouTubeThumbnailLoader thumbLoader;
String youTubeKey = null;
String videoId;

public ElementYoutubeHolder(View itemView) {
    super(itemView);
}

@Override
public void bind(final StoryElement element) {
    if (element.url() == null) {
        return;
    }
    Uri uri = Uri.parse(element.url());
    videoId = uri.getQueryParameter("v");
    thumbView.setTag(videoId);
    thumbView.initialize(youTubeKey, this);
    thumbView.setImageResource(R.drawable.placeholder);

    itemView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
        @Override
        public void onViewAttachedToWindow(View view) {

        }

        @Override
        public void onViewDetachedFromWindow(View view) {
            itemView.removeOnAttachStateChangeListener(this);
            if (thumbLoader != null) {
                try {
                    thumbLoader.setOnThumbnailLoadedListener(null);
                    thumbLoader.release();
                    Log.v(ElementYoutubeHolder.class.getSimpleName(), "thumbLoader released");
                } catch (IllegalStateException ile) {
                    //May be this youtube thumbnail loader already is released, so catch the exception here
                }
            }
        }
    });
    itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = YouTubeStandalonePlayer.createVideoIntent((Activity) view.getContext(), youTubeKey, videoId);
            view.getContext().startActivity(intent);
        }
    });
}

@Override
public View getView() {
    return itemView;
}

@Override
public boolean recreate() {
    return true;
}

/**
 * Static method to get YoutubeHolder
 *
 * @param parent {@link ViewGroup}
 * @return {@link ElementYoutubeHolder}
 */
public static ElementYoutubeHolder create(ViewGroup parent) {
    Log.v(ElementYoutubeHolder.class.getSimpleName(), "created element youtube holder");
    View view = ViewUtils.inflate(R.layout.qs_story_layout_youtube, parent);
    ElementYoutubeHolder holder = new ElementYoutubeHolder(view);
    holder.thumbView = (YouTubeThumbnailView) view.findViewById(R.id.qs_youtube_thumbnail);
    holder.youTubeKey = parent.getContext().getString(R.string.qs_youtube_key);
    return holder;
}

@Override
public void onInitializationSuccess(YouTubeThumbnailView youTubeThumbnailView, YouTubeThumbnailLoader youTubeThumbnailLoader) {
    Log.v(ElementYoutubeHolder.class.getSimpleName(), "initialization success");
    String videoId = (String) youTubeThumbnailView.getTag();
    youTubeThumbnailLoader.setVideo(videoId);
    thumbLoader = youTubeThumbnailLoader;
}

@Override
public void onInitializationFailure(YouTubeThumbnailView youTubeThumbnailView, YouTubeInitializationResult youTubeInitializationResult) {
    Log.v(ElementYoutubeHolder.class.getSimpleName(), "initialization failure: " + youTubeInitializationResult.toString());
    thumbLoader = null;
}

public void recycleYoutubeThumbnailLoader() {
    if (thumbLoader != null) {
        thumbLoader.release();
    }
}
}

我也是这样从适配器调用recycleYoutubeThumbnailLoader()

@Override
public void onViewDetachedFromWindow(BaseElementHolder holder) {
    if(holder instanceof ElementYoutubeHolder){
        ((ElementYoutubeHolder) holder).recycleYoutubeThumbnailLoader();
        Log.v(StoryAdapter.class.getSimpleName(), "thumnailLoader recycled");
    }
    super.onViewDetachedFromWindow(holder);
}

还有一件事:此错误并未导致我的应用崩溃。我的应用正常运行。只有这个错误出现在LogCat上,我想修复它,因为它可能会在以后引起更大的问题。

这是堆栈跟踪:

06-14 19:44:49.345 4688-4688/com.example.sampleapp E/ActivityThread: Activity com.example.sampleapp.DetailActivity has leaked ServiceConnection com.google.android.youtube.player.internal.r$e@1ece5fa2 that was originally bound here
                                                                             android.app.ServiceConnectionLeaked: Activity com.example.sampleapp.DetailActivity has leaked ServiceConnection com.google.android.youtube.player.internal.r$e@1ece5fa2 that was originally bound here
                                                                                 at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:1083)
                                                                                 at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:977)
                                                                                 at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1794)
                                                                                 at android.app.ContextImpl.bindService(ContextImpl.java:1777)
                                                                                 at android.content.ContextWrapper.bindService(ContextWrapper.java:539)
                                                                                 at com.google.android.youtube.player.internal.r.e(Unknown Source)
                                                                                 at com.google.android.youtube.player.YouTubeThumbnailView.initialize(Unknown Source)
                                                                                 at com.example.sampleapp.viewholders.ElementYoutubeHolder.bind(ElementYoutubeHolder.java:42)
                                                                                 at com.quintype.coreui.story.StoryPresenter.bind(StoryPresenter.java:281)
                                                                                 at com.example.sampleapp.adapters.StoryAdapter.onBindViewHolder(StoryAdapter.java:77)
                                                                                 at com.example.sampleapp.adapters.StoryAdapter.onBindViewHolder(StoryAdapter.java:40)
                                                                                 at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5471)
                                                                                 at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5504)
                                                                                 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4741)
                                                                                 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4617)
                                                                                 at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1994)
                                                                                 at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1390)
                                                                                 at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1353)
                                                                                 at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:574)
                                                                                 at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3028)
                                                                                 at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:2625)
                                                                                 at android.view.View.measure(View.java:17637)
                                                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5536)
                                                                                 at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
                                                                                 at android.view.View.measure(View.java:17637)
                                                                                 at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1560)
                                                                                 at android.view.View.measure(View.java:17637)
                                                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5536)
                                                                                 at android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:668)
                                                                                 at android.support.design.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:735)
                                                                                 at android.view.View.measure(View.java:17637)
                                                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5536)
                                                                                 at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
                                                                                 at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:135)
                                                                                 at android.view.View.measure(View.java:17637)
                                                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5536)
                                                                                 at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
                                                                                 at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
                                                                                 at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
                                                                                 at android.view.View.measure(View.java:17637)
                                                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5536)
                                                                                 at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
                                                                                 at android.view.View.measure(View.java:17637)
                                                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5536)
                                                                                 at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
                                                                                 at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
                                                                                 at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
                                                                                 at android.view.View.measure(View.java:17637)
                                                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5536)
                                                                                at android.widget.FrameLayout.onMeasure(Fra

1 个答案:

答案 0 :(得分:0)

您有一些服务,并在某处bindService呼叫。所以,您只需要致电unbindService

这是Context方法之一。如果您打开连接,则需要使用onDestroy方法(或不需要更多方法)将其关闭。