【问题标题】:YouTubeThumbnailView in List View列表视图中的 YouTubeThumbnailView
【发布时间】:2013-11-07 20:35:24
【问题描述】:

我正在使用 YouTube API 播放来自 YouTube 的视频(显然),到目前为止效果很好。我遇到的问题是我使用列表视图来显示不同的视频标题和缩略图,这需要自定义适配器和 YouTubeThumbnailView。

现在我的代码运行良好,因为它可以加载缩略图并将它们正确存储在地图中,但是当重新创建视图并且需要再次从地图中检索缩略图时,它有时会显示错误的并且经常重复。

这是适配器代码:

public class VideoListAdapter extends BaseAdapter implements
    YouTubeThumbnailView.OnInitializedListener{

Map<View, YouTubeThumbnailLoader> mLoaders;

public VideoListAdapter(final Context context, final List<Video> list, final int layoutResourceId) {
    mList = VideoManager.getInstance().getContentList();
    this.mLayID = layoutResourceId;
    this.mContext = context;
    mList = list;
    mLoaders = new HashMap<View, YouTubeThumbnailLoader>();
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View mCurrentRow = convertView;
    PostHolder holder;
    String videoId = mList.get(position).videoId;

    if(mCurrentRow == null)
    {
        LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
        mCurrentRow = inflater.inflate(mLayID, parent, false);

        holder = new PostHolder();
        holder.txtTitle = (TextView)mCurrentRow.findViewById(R.id.list_content_title);
        holder.txtTitle.setText(mList.get(position).title);

        //Case 1 - Initalise the thumbnail
        holder.thumb = (YouTubeThumbnailView) mCurrentRow.findViewById(R.id.list_content_thumb);
        holder.thumb.setTag(videoId);
        holder.thumb.initialize(Utils.DEVELOPER_KEY, this);

        mCurrentRow.setTag(holder);
    }
    else
    {
        holder = (PostHolder) mCurrentRow.getTag();
        YouTubeThumbnailLoader loader = mLoaders.get(holder.thumb);

        //Set the title
        Video post = mList.get(position);
        if(post != null){
            holder.txtTitle.setText(post.title);
        }

        if (holder.loader == null)
        {
            //Case 2 - Loader is currently initializing
           holder.thumb.setTag(videoId);
        } else
        {
            //Case 3 - The loader is already initialised
            holder.thumb.setImageResource(R.drawable.ic_launcher);
            holder.loader.setVideo(videoId);
        }
    }
    return mCurrentRow;
}

@Override
public void onInitializationSuccess(YouTubeThumbnailView view, YouTubeThumbnailLoader loader) {
    String videoId = (String) view.getTag();
    mLoaders.put(view, loader);
    view.setImageResource(R.drawable.ic_launcher);
    loader.setVideo(videoId);
}

@Override
public void onInitializationFailure(
        YouTubeThumbnailView thumbnailView, YouTubeInitializationResult errorReason) {
    if (errorReason.isUserRecoverableError()) {
        if (errorDialog == null || !errorDialog.isShowing()) {
            //errorDialog = errorReason.getErrorDialog(, RECOVERY_DIALOG_REQUEST);
            errorDialog.show();
        }
    } else {
        /*String errorMessage =
                String.format(getString(R.string.error_thumbnail_view), errorReason.toString());
        Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();*/
    }
}

static class PostHolder
{
    YouTubeThumbnailView thumb;
    YouTubeThumbnailLoader loader;
    TextView txtTitle;
    TextView txtTime;
}

我已经阅读了我所能阅读的文档,并查看了示例应用程序,但我没有找到任何可以帮助我的东西。这可能不是 YT API 的问题,而是我存储 ImageView 的方式的问题。

如果有人可以提供任何帮助,我将不胜感激,在此先感谢。

【问题讨论】:

    标签: android listview youtube thumbnails


    【解决方案1】:

    您不能将 YouTubeThumbnailLoader 保存在 PostHolder 类中,而是让所有加载程序由 mLoaders HashMap 处理。正如您在 cmets 中所意识到的,您需要此 HashMap 通过回调设置加载程序。因此,将 getView() 方法的 else 部分更改为:

         } else {
    
            holder = (PostHolder) convertView.getTag();
    
            //Set the title
            Video post = mList.get(position);
            if(post != null){
                holder.txtTitle.setText(post.title);
            }
    
            // 2) and 3) The view is already created...
            YouTubeThumbnailLoader loader = mLoaders.get(holder.thumbnailView);
    
            // ...and is currently being initialized. We store the current videoId in the tag.
            if (loader == null) {
                holder.thumbnailView.setTag(videoId);
    
            // ...and already initialized. Simply set the right videoId on the loader.
            } else {
                holder.thumbnailView.setImageResource(R.drawable.ic_launcher);
                loader.setVideo(videoId);
    
            }
        }
    

    您的 Post Holder 类不需要加载器:

     static class PostHolder
     {
       YouTubeThumbnailView thumbnailView;
       TextView txtTitle;
       TextView txtTime;
     }
    

    【讨论】:

    • 我不能完全删除 HashMap,只需像我所做的那样将 YouTubeThumbnailLoader 放在支架中,然后删除此行:YouTubeThumbnailLoader loader = mLoaders.get(holder.thumbnailView);这样做后,它似乎加快了缩略图的加载速度,因为使用此 line holder = (PostHolder) mCurrentRow.getTag(); 检索缩略图无需搜索 HashMap。
    • 嗯,是的,只要您只需要 PostHolder 上下文中的加载程序,这应该没问题。在我的情况下,我还需要它在 getView()-Method 之外,因此作为我的适配器的一个类字段。我将编辑我的答案以显示这两个选项。性能差异真的那么大吗?如果是,我会考虑在我的应用程序中重构我的方法;)
    • 实际上刚刚尝试过,我意识到我的逻辑错误,将 thumbnailLoader 存储在支架中会很好,只要你可以把它放在那里。由于您需要等到 onInitializationSuccess 被调用才能对加载器执行任何操作,因此您不再有权访问持有者来存储它。您可以在第二次创建视图时存储它: holder.loader = mLoaders.get(holder.thumb);但这可能会增加开销。
    • 作为一个额外的问题,当你改变方向时,你是否曾经不得不处理这个问题:MainActivity 泄露了 ServiceConnection com.google.android.youtube.player.internal.r$e@4266b068原本是绑定在这里的。我在想我可能需要从地图上释放加载器或对 PlayerView 做一些事情。
    • 哈哈你是对的,我再次编辑了答案。我自己没想到... :) 是的,你的奖金问题敲响了警钟..我记得 HashMap 上有一个 for 循环,在所有现有加载器上调用 loader.release() ......但我没有偶然发现了这个确切的错误,对不起
    猜你喜欢
    • 1970-01-01
    • 2016-11-25
    • 2013-12-04
    • 2012-09-24
    • 1970-01-01
    • 2012-07-24
    • 1970-01-01
    • 1970-01-01
    • 2018-01-17
    相关资源
    最近更新 更多