2015-12-19 7 views
19

Sto tentando di caricare le miniature dei video di YouTube in un RecyclerView. Sto affrontando alcuni problemiCome caricare le miniature di YouTube in un RecyclerView utilizzando l'API di YouTube

Ecco quello che sto facendo nel mio adattatore:

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) { 

       }}); 
}}} 

Funziona bene, ma non mi sto facendo bene. Quando sto utilizzando la stessa scheda in un'altra attività ottengo questo errore:

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

e ci vuole tempo per caricare le miniature ed a volte mix tra loro quando strisciata.

ho aggiunto una funzione di liberare tutti i Pale Youtube:

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

e sto chiamando questa funzione dal Activity OnStop():

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

ha funzionato bene per un certo tempo, ma a volte si blocca.

+0

Hai controllato [questo SO biglietto] (http://stackoverflow.com/questions/1992676/i-cant -get-RID-of-questo-error-message-activity-app-name-ha-trapelato-servicecon)? Sembra che abbia lo stesso problema che stai incontrando - la perdita di memoria, non la RecyclerView, sembra che tu l'abbia già gestita. – adjuremods

+0

L'errore proviene dall'adattatore Recylcerview –

+0

Come si inizializza l'adattatore? – random

risposta

26

Si può provare questo forse? Non usa l'API ma è veloce.

Caricare l'immagine nella vista riciclatore con Picasso da questo URL:

https://img.youtube.com/vi/ "qui va il video id" /default.jpg

- Modifica -

Dopo qualche ricerca e esperimenti:

Per Crea anteprima a schermo intero di default fare questo, invece di default.jpg

https://img.youtube.com/vi/ "ecco il tuo ID video"/0.jpg

Ecco il link: http://www.reelseo.com/youtube-thumbnail-image/

Edit 2:

Appena trovato qualcuno in SO già dato una risposta come la mia con questa soluzione veloce e semplice e ha modo più spiegazioni e le opzioni si può scegliere da .

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


Edit finale:

Questo è il codice funziona. Sono entrato e ho fatto un'app di recente con l'API, così ho scoperto perché stai ricevendo l'errore. È perché non stai rilasciando correttamente il caricatore.

È possibile rilasciare caricatore/caricatore in due modi.

Prima

(preferito, si vedrà perché in un secondo) Si vorrebbe rilasciarlo dopo che l'immagine è stata caricata in vista e c'è un ascoltatore per questo e la sua chiamata OnThumbNailLoadedListener. Ecco dove l'ho rilasciato (se presti attenzione al codice qui sotto). Ciò significa che non dovrai più occuparti di questa istanza. Una volta caricata la miniatura, hai finito.

Seconda

Dal GetView() viene chiamato per tutto il tempo ci sono nuove istanze di YouTubeThumbnailLoader che si deve liberare. Ciò significa che devi archiviarli tutti in un ArrayList. Basta fare un ciclo avanzato per il rilascio di chiamate in tutte quando l'attività è onStop();

Ora probabilmente si vede perché è preferibile la prima. E so che hai fatto la seconda opzione, quindi ti faccio sapere che la prima opzione sarà sempre garantita per funzionare (almeno nel mio caso). Ho utilizzato YouTubeSupportFragment in un'attività e ha funzionato correttamente. Nessun problema. Puoi sicuramente far funzionare la seconda opzione, ma dovresti gestire molti casi speciali che penso.

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

Questa è l'opzione migliore! grazie –

+0

Ho appena apportato una buona modifica alla mia risposta. Ti suggerisco di dare un'occhiata. –

+0

Grazie mille amico .. !! –

11

In onBindViewHolder si sta tentando di inizializzare lo stesso YoutubeThumbnailView ancora e ancora, invece è possibile inizializzarlo una volta quando vengono create le viste in onCreateViewHolder. Impostando ID video come tag su un YoutubeThumbnailView, è possibile evitare il missaggio (o il caricamento errato di anteprime).


Adattatore.

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(); 
    } 
} 

Il layout utilizzato per ogni riga è.

<?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.

Località: src/main/res/valori/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

Grazie per la tua risposta, ma l'ho provato e le miniature ancora si mescolano! –

+0

Lo sto usando nella mia app. Sta funzionando bene. Le miniature non verranno mescolate. –

0

public class VideoAdapter estende 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; 
} 

}