2015-12-19 1 views
19

Я пытаюсь загрузить миниатюры видео Youtube в RecyclerView. Я столкнулся с некоторыми проблемами.Как загрузить миниатюры Youtube в RecyclerView с использованием API Youtube

Вот что я делаю в моем адаптере:

public static class ItemViewHolder extends RecyclerView.ViewHolder { 

    private YouTubeThumbnailView thumb; 
    public Post     post; 

    public ItemViewHolder(View v) { 
     thumb = (YouTubeThumbnailView) v.findViewById(R.id.youtube_thumbnail); 
    } 

    @Override 
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) { 
     if (holder instanceof ItemViewHolder) { 

      ((ItemViewHolder) holder).thumb.initialize(YOUTUPEKEY, new YouTubeThumbnailView.OnInitializedListener() { 
       @Override 
       public void onInitializationSuccess(YouTubeThumbnailView youTubeThumbnailView, YouTubeThumbnailLoader youTubeThumbnailLoader) { 
        youTubeThumbnailLoader.setVideo(VIDEOID); 

       } 

       @Override 
       public void onInitializationFailure(YouTubeThumbnailView youTubeThumbnailView, YouTubeInitializationResult youTubeInitializationResult) { 

       }}); 
}}} 

Он отлично работает, но я не делаю это правильно. Когда я использую один и тот же адаптер в другой деятельности, я получаю эту ошибку:

Activity com.example.yasser.version6.Mespublications has leaked ServiceConnection [email protected] that was originally bound here 

и требуется время, чтобы загрузить эскизы и иногда смешиваются между ними, когда ударяя.

Я добавил функцию, чтобы освободить все погрузчики Youtube:

public void ReleaseLoaders() { 
    for (YouTubeThumbnailLoader loader : loaders.values()) { 
     loader.release(); 
    } 
} 

и я вызывающий эту функцию от активности OnStop():

@Override 
public void onStop() { 
    super.onStop(); 
    mAdapter.ReleaseLoaders(); 
} 

Он работал отлично на некоторое время, но иногда случается сбой.

+0

вы проверили [этот SO билет] (http://stackoverflow.com/questions/1992676/i-cant -get-РИД-из-этого-сообщения об ошибке-активности-приложение-имя-имеет-просочилась-servicecon)? Кажется, у вас такая же проблема, с которой вы сталкиваетесь - утечка памяти, а не RecyclerView, похоже, вы уже справлялись с этим. – adjuremods

+0

Ошибка происходит от адаптера Recylcerview –

+0

Как вы инициализируете свой адаптер? – random

ответ

26

Вы можете попробовать это может быть? Он не использует API, но быстро.

Загрузите изображение в окне ресайклера с Пикассо из этого URL:

https://img.youtube.com/vi/ "здесь идет ваш идентификатор видео" /default.jpg

- Edit -

После некоторых исследований и эксперименты:

Чтобы получить по умолчанию эскиза полного размера сделать это вместо default.jpg

https://img.youtube.com/vi/ "здесь идет ваш идентификатор видео"/0.JPG

Вот ссылка: http://www.reelseo.com/youtube-thumbnail-image/

Edit 2:

Просто найти кого-то в SO уже дал ответ, как у меня с этим быстрым и простым решением и имеет намного больше объяснений и вариантов вы можете выбрать один из ,

How do I get a YouTube video thumbnail from the YouTube API?


Final Edit:

Это рабочий код. Я вошел и недавно сделал приложение с api, поэтому выяснил, почему вы получаете ошибку. Это потому, что вы не освобождаете загрузчик должным образом.

Вы можете разгрузить погрузчик/погрузчики двумя способами.

Первый

(Preferred, вы поймете, почему в сек) Вы хотели бы, чтобы освободить его после того, как изображение было загружено в поле зрения и Тереза ​​слушателя для этого и его названием OnThumbNailLoadedListener. То, где я его выпустил (если вы обратите внимание на приведенный ниже код). Это означает, что вам больше не нужно иметь дело с этим экземпляром. Как только эскиз загружен, вы сделали.

Второй

С GetView() вызывается все время есть новые экземпляры YouTubeThumbnailLoader, которые вы должны освободить. Это означает, что вы должны хранить все это в ArrayList. Вы просто выполняете расширенный цикл для цикла и вызова во всех случаях, когда активность onStop();

Теперь вы, вероятно, видите, почему предпочитается первый способ. И я знаю, что вы сделали второй вариант, поэтому просто сообщив, что первый вариант всегда будет гарантированно работать (по крайней мере, в моем случае). Я использовал функцию YouTubeSupportFragment в Activity, и она отлично работала. Никаких проблем. Вы можете определенно сделать второй вариант работы, но вам придется обрабатывать множество особых случаев, я думаю.

final YouTubeThumbnailView youTubeThumbnailView = (YouTubeThumbnailView) convertView.findViewById(R.id.show_episode_thumbnail); 
    youTubeThumbnailView.initialize(DeveloperKey.DEVELOPER_KEY, new YouTubeThumbnailView.OnInitializedListener() { 
     @Override 
     public void onInitializationSuccess(YouTubeThumbnailView youTubeThumbnailView, final YouTubeThumbnailLoader youTubeThumbnailLoader) { 
      youTubeThumbnailLoader.setVideo(videoId); 
      youTubeThumbnailLoader.setOnThumbnailLoadedListener(new YouTubeThumbnailLoader.OnThumbnailLoadedListener() { 
       @Override 
       public void onThumbnailLoaded(YouTubeThumbnailView youTubeThumbnailView, String s) { 
        youTubeThumbnailLoader.release(); 
       } 

       @Override 
       public void onThumbnailError(YouTubeThumbnailView youTubeThumbnailView, YouTubeThumbnailLoader.ErrorReason errorReason) { 

       } 
      }); 
     } 

     @Override 
     public void onInitializationFailure(YouTubeThumbnailView youTubeThumbnailView, YouTubeInitializationResult youTubeInitializationResult) { 

     } 
    }); 
+0

Это лучший вариант! спасибо –

+0

Просто сделал хорошее редактирование для моего ответа. Я предлагаю вам взглянуть. –

+0

Большое спасибо чувак .. !! –

11

В onBindViewHolder вы пытаетесь инициализировать то же самое YoutubeThumbnailView снова и снова, вместо этого вы можете инициализировать его один раз, когда представления создаются в onCreateViewHolder. Установив видео Id как тег на YoutubeThumbnailView, вы можете предотвратить смешение (или) неправильной загрузки миниатюр.


Адаптер.

private class ThumbnailAdapter extends RecyclerView.Adapter{ 

    private final int UNINITIALIZED = 1; 
    private final int INITIALIZING = 2; 
    private final int INITIALIZED = 3; 
    private int blackColor = Color.parseColor("#FF000000"); 
    private int transparentColor = Color.parseColor("#00000000"); 

    public class VideoViewHolder extends RecyclerView.ViewHolder{ 

     public YouTubeThumbnailView ytThubnailView = null; 
     public ImageView ivYtLogo = null; 
     public TextView tvTitle = null; 

     public VideoViewHolder(View itemView) { 
      super(itemView); 
      ytThubnailView = (YouTubeThumbnailView) itemView.findViewById(R.id.yt_thumbnail); 
      ivYtLogo = (ImageView) itemView.findViewById(R.id.iv_yt_logo); 
      tvTitle = (TextView) itemView.findViewById(R.id.tv_title); 

      initialize(); 
     } 

     public void initialize(){ 
      ivYtLogo.setBackgroundColor(blackColor); 
      ytThubnailView.setTag(R.id.initialize, INITIALIZING); 
      ytThubnailView.setTag(R.id.thumbnailloader, null); 
      ytThubnailView.setTag(R.id.videoid, ""); 

      ytThubnailView.initialize(API_KEY, new YouTubeThumbnailView.OnInitializedListener() { 
       @Override 
       public void onInitializationSuccess(YouTubeThumbnailView youTubeThumbnailView, YouTubeThumbnailLoader youTubeThumbnailLoader) { 
        ytThubnailView.setTag(R.id.initialize, INITIALIZED); 
        ytThubnailView.setTag(R.id.thumbnailloader, youTubeThumbnailLoader); 

        youTubeThumbnailLoader.setOnThumbnailLoadedListener(new YouTubeThumbnailLoader.OnThumbnailLoadedListener() { 
         @Override 
         public void onThumbnailLoaded(YouTubeThumbnailView youTubeThumbnailView, String loadedVideoId) { 
          String currentVideoId = (String) ytThubnailView.getTag(R.id.videoid); 
          if(currentVideoId.equals(loadedVideoId)) { 
           ivYtLogo.setBackgroundColor(transparentColor); 
          } 
          else{ 
           ivYtLogo.setBackgroundColor(blackColor); 
          } 
         } 

         @Override 
         public void onThumbnailError(YouTubeThumbnailView youTubeThumbnailView, YouTubeThumbnailLoader.ErrorReason errorReason) { 
          ivYtLogo.setBackgroundColor(blackColor); 
         } 
        }); 

        String videoId = (String) ytThubnailView.getTag(R.id.videoid); 
        if(videoId != null && !videoId.isEmpty()){ 
         youTubeThumbnailLoader.setVideo(videoId); 
        } 
       } 

       @Override 
       public void onInitializationFailure(YouTubeThumbnailView youTubeThumbnailView, YouTubeInitializationResult youTubeInitializationResult) { 
        ytThubnailView.setTag(R.id.initialize, UNINITIALIZED); 
        ivYtLogo.setBackgroundColor(blackColor); 
       } 
      }); 
     } 
    } 

    @Override 
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View view = getLayoutInflater().inflate(R.layout.row_video_item, parent, false); 
     VideoViewHolder videoViewHolder = new VideoViewHolder(view); 
     return videoViewHolder; 
    } 

    @Override 
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
     final Entities e = entities.get(position); 
     final VideoViewHolder videoViewHolder = (VideoViewHolder) holder; 
     videoViewHolder.tvTitle.setText(e.name); 
     videoViewHolder.ivYtLogo.setVisibility(View.VISIBLE); 
     videoViewHolder.ytThubnailView.setTag(R.id.videoid, e.id); 
     videoViewHolder.ivYtLogo.setBackgroundColor(blackColor); 

     int state = (int) videoViewHolder.ytThubnailView.getTag(R.id.initialize); 

     if(state == UNINITIALIZED){ 
      videoViewHolder.initialize(); 
     } 
     else if(state == INITIALIZED){ 
      YouTubeThumbnailLoader loader = (YouTubeThumbnailLoader) videoViewHolder.ytThubnailView.getTag(R.id.thumbnailloader); 
      loader.setVideo(e.id); 
     } 
    } 

    @Override 
    public int getItemCount() { 
     return entities.size(); 
    } 
} 

Схема используется для каждой строки.

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" android:layout_width="match_parent" 
android:layout_height="match_parent"> 

<RelativeLayout 
    android:layout_width="match_parent" 
    android:layout_height="200dp"> 

    <com.google.android.youtube.player.YouTubeThumbnailView 
     android:id="@+id/yt_thumbnail" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" /> 

    <ImageView 
     android:id="@+id/iv_yt_logo" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:scaleType="center" 
     android:src="@mipmap/youtube_play" 
     android:background="#00000000" 
     android:layout_centerInParent="true"/> 

</RelativeLayout> 

<TextView 
    android:id="@+id/tv_title" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:textColor="#FF000000" 
    android:textSize="16sp" 
    android:text="Title"/> 

<View 
    android:id="@+id/seperator" 
    android:layout_width="match_parent" 
    android:layout_height="2dp" 
    android:layout_marginTop="5dp" 
    android:layout_marginBottom="5dp" 
    android:background="#FF642108"/> 

</LinearLayout> 

tags.xml.

Расположение: SRC/основные/RES/значения/tags.xml

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
<item type="id" name="initialize" /> 
<item type="id" name="videoid"/> 
<item type="id" name="thumbnailloader"/> 
</resources> 

enter image description here

+0

Спасибо за ваш ответ, но я попробовал его, а миниатюры все еще перемешиваются! –

+0

Я использую его в своем приложении. Он работает нормально. Миниатюры не будут смешиваться. –

0

общественного класса видеоадаптера расширяет RecyclerView.Adapter {

private List<VideoPojo> listvideo; 
private VideoPojo videoPojo; 
private Context mContext; 
private boolean readyForLoadingYoutubeThumbnail = true; 
String KEY = "AIzaSyA5kyaLgS7MKxS19uHf2CUsIOmDkv92DGU"; 

public VideoAdapter(Context context, List<VideoPojo> listvideo) { 
    this.listvideo = listvideo; 
    this.mContext = context; 
    videoPojo = new VideoPojo(); 
} 

@Override 
public VideoAdapter.VideoHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.video_layout, parent, false); 
    return new VideoHolder(view); 
} 

@Override 
public void onBindViewHolder(final VideoAdapter.VideoHolder holder, final int position) { 

    holder.murl.setText(listvideo.get(position).getVideoUrl()); 
    final String url = listvideo.get(position).getVideoUrl(); 
    Log.d(TAG, "readyForLoadingYoutubeThumbnail" + readyForLoadingYoutubeThumbnail); 
    if (readyForLoadingYoutubeThumbnail) { 
     Log.d(TAG, "initializing for youtube thumbnail view..."); 
     readyForLoadingYoutubeThumbnail = false; 
     holder.youTubeThumbnailView.initialize(KEY, new YouTubeThumbnailView.OnInitializedListener() { 
      @Override 
      public void onInitializationSuccess(final YouTubeThumbnailView youTubeThumbnailView, final YouTubeThumbnailLoader youTubeThumbnailLoader) { 

       youTubeThumbnailLoader.setVideo(url); 
       youTubeThumbnailLoader.setOnThumbnailLoadedListener(new YouTubeThumbnailLoader.OnThumbnailLoadedListener() { 

        @Override 
        public void onThumbnailLoaded(YouTubeThumbnailView childYouTubeThumbnailView, String s) { 
         holder.loding.setVisibility(View.GONE); 
         youTubeThumbnailLoader.release(); // spy ga memory lick 
        } 

        @Override 
        public void onThumbnailError(YouTubeThumbnailView youTubeThumbnailView, YouTubeThumbnailLoader.ErrorReason errorReason) { 
         youTubeThumbnailLoader.release(); // spy ga memory lick 
        } 
       }); 

       readyForLoadingYoutubeThumbnail = true; 
      } 

      @Override 
      public void onInitializationFailure(YouTubeThumbnailView youTubeThumbnailView, YouTubeInitializationResult youTubeInitializationResult) { 
       //do nohing.. ada error, tambahin method ini jalan, error-nya lupa... 
       readyForLoadingYoutubeThumbnail = true; 
      } 
     }); 
    } 
    holder.mdelate.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      deleteVideoAlertDialog(listvideo.get(holder.getAdapterPosition()).getId(), holder.getAdapterPosition()); 
     } 
    }); 

} 

@Override 
public int getItemCount() { 
    // Log.v(VideoAdapter.class.getSimpleName(), "" + listvideo.size()); 
    return listvideo.size(); 
} 

public class VideoHolder extends RecyclerView.ViewHolder { 

    YouTubeThumbnailView youTubeThumbnailView; 
    protected FrameLayout playButton; 
    TextView murl, mdelate; 
    ImageView loding; 

    public VideoHolder(View itemView) { 
     super(itemView); 
     mdelate = itemView.findViewById(R.id.mdelate); 
     murl = itemView.findViewById(R.id.murl); 
     playButton = itemView.findViewById(R.id.btnYoutube_player); 
     youTubeThumbnailView = itemView.findViewById(R.id.youtube_thumbnail); 
     loding = itemView.findViewById(R.id.loding); 

     playButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       int position = getAdapterPosition(); 
       String url = listvideo.get(position).getVideoUrl(); 
       Toast.makeText(mContext, url, Toast.LENGTH_SHORT).show(); 
       Intent intent = YouTubeStandalonePlayer.createVideoIntent((Activity) mContext, 
         KEY, url, 100, false, true); 
       mContext.startActivity(intent); 
      } 
     }); 
    } 

} 

private void deleteVideoAlertDialog(final int row_id, final int adapterPosition) { 
    final AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext); 

    // Setting Dialog Title 
    alertDialog.setTitle("Delete"); 
    // Setting Dialog Message 
    alertDialog.setMessage("Are you sure you want to delete this video"); 
    alertDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int which) { 
      if (SQLiteHelper.deleteUser(mContext, row_id)) { 
       listvideo.remove(adapterPosition); 
       notifyItemRemoved(adapterPosition); 
       notifyItemRangeChanged(adapterPosition, listvideo.size()); 
      } else { 
       Toast.makeText(mContext, "internal issue ", Toast.LENGTH_SHORT).show(); 
      } 
     } 
    }); 
    // Setting Negative "NO" Button 
    alertDialog.setNegativeButton("No", new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int which) { 
      // Write your code here to invoke NO event 
      dialog.cancel(); 
     } 
    }); 
    // Showing Alert Message 
    alertDialog.show(); 

} 

public boolean addNewVideo(String Url, Context context) { 
    videoPojo.setVideoUrl(Url); 
    SQLiteHelper sqLiteHelper = new SQLiteHelper(context); 
    if (sqLiteHelper.addNewVideo(context, videoPojo)) { 
     listvideo.add(videoPojo); 
     notifyDataSetChanged(); 
     Toast.makeText(context, "video Saved", Toast.LENGTH_SHORT).show(); 
     return true; 
    } 
    return false; 
} 

}