2017-02-17 14 views
6

Mam utworzony gridview, który pokazuje filmy z serwera. GridItem ma obraz kciuka wideo i czas trwania wideo. Do ładowania kciuka wideo Używam UniversalImageloader i ładuję czas trwania wideo, tworząc lazyloading używając asynctask.Lazyloading działa dobrze. ale jeśli ktoś przewinnie gridview z odpowiednią szybkością, czas trwania filmu będzie wyświetlany w niewłaściwym miejscu. do tworzenia Lazyloading śledzę poniżej linkWidok tekstu Lazyloading, setText w złym miejscu w widoku siatki?

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    final TextView durationTextView; 

    View view = null; 
    if (convertView == null) { 
     view = mInflater.inflate(R.layout.camera_roll_item, parent, false); 

     MediaItemViewHolder mediaItemViewHolder = new MediaItemViewHolder(); 
     mediaItemViewHolder.highlightTagIcon = (ImageView) view.findViewById(R.id.iv_media_grid_item_highlight_tag); 
     mediaItemViewHolder.mediaTypeIcon = (ImageView) view.findViewById(R.id.iv_media_grid_item_type); 
     mediaItemViewHolder.mediaClipLength = (TextView) view.findViewById(R.id.tv_media_grid_item_length); 
     mediaItemViewHolder.mediaThumbnail = (ImageView) view.findViewById(R.id.iv_media_grid_item_thumbnail); 
     mediaItemViewHolder.cameraItemSelectedView = (RelativeLayout) view.findViewById(R.id.rl_item_selection_parent); 
     mediaItemViewHolder.progressContainer = (RelativeLayout) view.findViewById(R.id.rl_grid_loader_parent); 
     view.setTag(mediaItemViewHolder); 
    } else { 
     view = convertView;//(MediaItemViewHolder) convertView.getTag(); 
     //mediaItemViewHolder.mediaClipLength.setText(""); 
     Log.i(TAG, "set blank to "); 
    } 
    MediaItemViewHolder mediaItemViewHolder = (MediaItemViewHolder) convertView.getTag(); 
    durationTextView = mediaItemViewHolder.mediaClipLength; 
    if (position >= mCameraMediaItems.size()) { 
     Log.d(TAG, "Index out of Bound, position:" + position + " - mCameraMediaItems.size():" + mCameraMediaItems.size()); 
     return convertView; 
    } 
    MediaItemBean mediaItemBean = CameraMediaController.getInstance().getMediaItemByPosition(position); 
    mediaItemViewHolder.mediaClipLength.setVisibility(View.VISIBLE); 
    mediaItemViewHolder.highlightTagIcon.setVisibility(View.GONE); 

    if (mediaItemBean != null && mediaItemBean.getCameraMedia() != null) { 
     switch (mediaItemBean.getCameraMedia().getType()) { 
      case AppConstant.MEDIA_TYPE_VIDEO: 
       mediaItemViewHolder.mediaTypeIcon.setImageResource(R.drawable.icn_thumb_vid); 
       //VideoInfoAsyncTask loads data in this list 
       int videoDuration = mediaItemBean.getVideoDuration(); 
       //mediaItemViewHolder.mediaClipLength.setTag(CameraMediaUtil.convertSecondsTimeToMinutesString(videoDuration)); 
       Log.i(TAG, "VideoDuration " + videoDuration); 

       String resId = mediaItemBean.getCreatedId()+"video_media_duration_com.gopro.buckhorn"; 
       Log.i(TAG, "RESID "+resId); 
       downloadDuration(resId, durationTextView, mediaItemViewHolder.highlightTagIcon, mediaItemBean); 
       break; 
      case MULTI_PHOTO: 
       String mulCount = String.valueOf(Controller.getInstance().getPhotoCountAtPosition(position)); 
       Log.i("MULTI_SHOT_SECTION", "MultiShot "+mulCount); 
       mediaItemViewHolder.mediaTypeIcon.setImageResource(R.drawable.icn_thumb_burst); 
       mediaItemViewHolder.mediaClipLength.setText(mulCount); 
       break; 

     } 
     //Load image into image view from URL 
     String imageUri = mediaItemBean.getThumbnailUri().toString(); 
     Log.i(TAG, "Thumb url :" + imageUri); 
     mediaItemViewHolder.progressContainer.setVisibility(View.VISIBLE); 

     DownloadImageUtil.getLoadImageInsatnce().downloadGridImage(imageUri, 
       mediaItemViewHolder.mediaThumbnail, R.drawable.thumb_load, mediaItemViewHolder.progressContainer); 
    } 

    return convertView; 
} 


private void downloadDuration(String resId, TextView textView, ImageView highlightTagIcon, MediaItemBean mediaItemBean) { 
    String duration = getVideoDurationFromCache(String.valueOf(resId)); 
    Log.i(TAG, "downloadDuration " + duration); 
    if (duration == null) { 
     loadVideoDuration(resId, textView, highlightTagIcon, mediaItemBean); 
     textView.setText(""); 
    } else { 
     cancelVideoDurationDownloaderTask(resId, textView); 
     if(mediaItemBean.getCameraMedia().getType() == AppConstant.MEDIA_TYPE_VIDEO){ 
      textView.setText(duration); 
      if (mediaItemBean.isIsHighLightTags()) { 
       highlightTagIcon.setVisibility(View.VISIBLE); 
      } 
     } 
    } 
} 


private String getVideoDurationFromCache(String key) { 
    // First try the hard reference cache 
    synchronized (mMemoryCache) { 
     final String duration = mMemoryCache.get(key); 
     if (duration != null) { 
      // Bitmap found in hard cache 
      // Move element to first position, so that it is removed last 
      mMemoryCache.remove(key); 
      mMemoryCache.put(key, duration); 
      return duration; 
     } 
    } 
    return null; 
} 


private static class MediaItemViewHolder { 
    ImageView highlightTagIcon, mediaTypeIcon, mediaThumbnail; 
    TextView mediaClipLength; 
    RelativeLayout cameraItemSelectedView; 
    /* ProgressBar innerProgressBar; 
    ProgressBar outerProgressBar;*/ 
    RelativeLayout progressContainer; 
} 

public class VideoDurationDownloaderTask extends AsyncTask<String, Void, String> { 
    private final WeakReference<TextView> videoDurationReference; 
    private final WeakReference<ImageView> hiliteTagImageViewWeakReference; 
    private String data = ""; 
    private MediaItemBean mediaItemBean; 

    public VideoDurationDownloaderTask(TextView textView, ImageView hiliteTagIcon, MediaItemBean mediaItemBean) { 
     this.mediaItemBean = mediaItemBean; 
     videoDurationReference = new WeakReference<>(textView); 
     hiliteTagImageViewWeakReference = new WeakReference<>(hiliteTagIcon); 
    } 

    @Override 
    protected String doInBackground(String... params) { 
     data = params[0]; 
     Log.i(TAG, "data in task "+data); 
     return downloadVideoDuration(mediaItemBean); 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     super.onPostExecute(result); 
     if (isCancelled()) { 
      Log.i(TAG, "isCancelled " + result); 
      result = ""; 
     } 
     addDurationToMemoryCache(data, result); 
     //noinspection ConstantConditions 
     if (videoDurationReference != null) { 
      TextView videoDuration = videoDurationReference.get(); 
      Log.i(TAG, "videoDuration " + videoDuration); 
      VideoDurationDownloaderTask videoDurationDownloaderTask = 
        getTextViewDerationWorkerTask(videoDuration); 
      Log.i(TAG, "videoDurationDownloaderTask " + videoDurationDownloaderTask); 
      if (videoDuration != null) { 
       if (this == videoDurationDownloaderTask) { 
        if(mediaItemBean.getCameraMedia().getType() == AppConstant.MEDIA_TYPE_VIDEO) { 
         Log.i(TAG, "TAG VAL "+videoDuration.getTag()); 
         videoDuration.setText(result); 
         videoDuration.setTag(new TextView(context)); 
         if (mediaItemBean.isIsHighLightTags()) { 
          ImageView highlightTagIcon = hiliteTagImageViewWeakReference.get(); 
          if (highlightTagIcon != null) 
           highlightTagIcon.setVisibility(View.VISIBLE); 
         } 
        } 
       } 
      } 
     } 
    } 
} 

private String downloadVideoDuration(MediaItemBean mediaItemBean) { 
    try { 
     if (media != null && mediaItemBean.getMedia() != null) { 
      int videoDuration = mediaItemBean.getVideoDuration(); 
      Log.i(TAG, "Video has duration = " + videoDuration); 
      if (videoDuration == -1) { 
       CommandResult<Integer> duration = 
         media.getVideoDuration(mediaItemBean.getCameraMedia().getFilePath()); 
       videoDuration = duration.getData(); 
       mediaItemBean.setVideoDuration(videoDuration); 
       Log.i(TAG, "set Video Duration " + videoDuration); 
      } 
      return MediaUtil.convertSecondsTimeToMinutesString(videoDuration); 
     } 
    } catch (Exception e) { 
     Log.e(TAG, "Exception Occure while Getting video info:" + e.getMessage()); 
    } 
    Log.i(TAG, "not fetch duration "); 
    return ""; 
} 


public void loadVideoDuration(String resId, TextView textView, ImageView hiliteTagIcon, MediaItemBean mediaItemBean) { 
    if (cancelVideoDurationDownloaderTask(resId, textView)) { 
     final VideoDurationDownloaderTask task = new VideoDurationDownloaderTask(textView, hiliteTagIcon, mediaItemBean); 
     AsyncTextView asyncTextView = new AsyncTextView(context, task); 
     textView.setTag(asyncTextView); 
     task.execute(resId); 
    } 
} 

private boolean cancelVideoDurationDownloaderTask(String data, TextView textView) { 
    final VideoDurationDownloaderTask durationWorkerTask = getTextViewDerationWorkerTask(textView); 

    if (durationWorkerTask != null) { 
     final String textViewData = durationWorkerTask.data; 
     Log.i(TAG, textViewData + " textViewDataData, data " + data); 
     if (data != null && !textViewData.equalsIgnoreCase(data)) { 
      // Cancel previous task 
      Log.i(TAG, "Cancel previous task " + data); 
      durationWorkerTask.cancel(true); 
     } else { 
      // The same work is already in progress 
      Log.i(TAG, "same work is already in progress " + false); 
      return false; 
     } 
    } 
    // No task associated with the ImageView, or an existing task was 
    // cancelled 
    Log.i(TAG, "cancelVideoDurationDownloaderTask true"); 
    return true; 
} 

static class AsyncTextView extends TextView { 
    private final WeakReference<VideoDurationDownloaderTask> textviewWorkerTaskReference; 

    public AsyncTextView(Context context, VideoDurationDownloaderTask textviewWorkerTask) { 
     super(context); 
     textviewWorkerTaskReference = new WeakReference<>(textviewWorkerTask); 
    } 

    public VideoDurationDownloaderTask getTextViewWorkerTask() { 
     return textviewWorkerTaskReference.get(); 
    } 
} 

private static VideoDurationDownloaderTask getTextViewDerationWorkerTask(TextView textView) { 
    if(textView.getTag() != null){ 
     Log.i(TAG, " textView.getTag() " + textView.getTag()); 
     if (textView.getTag() instanceof AsyncTextView) { 
      Log.i(TAG, " Return Textview task"); 
      final AsyncTextView asyncTextView = (AsyncTextView) textView.getTag(); 
      return asyncTextView.getTextViewWorkerTask(); 
     } 
    } 
    return null; 
} 

public void addDurationToMemoryCache(String key, String duration) { 
    if (getBitmapFromMemCache(key) == null) { 
     mMemoryCache.put(key, duration); 
    } 
} 
+1

Po przesłaniu kodu do renderowania GridView, powiązania danych i leniwego ładowania rzeczy? –

+0

@AnuragSingh czy możesz zobaczyć implementację? –

+0

wykonaj poniższe zmiany, jak opisano poniżej. –

Odpowiedz

3

Pozbądź view i używać convertView po otrzymaniu od metody. Przejście do następnego

//final is optional but if you need to use in thread 
final MediaItemViewHolder mediaItemViewHolder = null; 
if (convertView == null) { 
    convertView = mInflater.inflate(R.layout.camera_roll_item, parent, false); 

    mediaItemViewHolder = new MediaItemViewHolder(); 
    mediaItemViewHolder.highlightTagIcon = (ImageView) convertView.findViewById(R.id.iv_media_grid_item_highlight_tag); 
    mediaItemViewHolder.mediaTypeIcon = (ImageView) convertView.findViewById(R.id.iv_media_grid_item_type); 
    mediaItemViewHolder.mediaClipLength = (TextView) convertView.findViewById(R.id.tv_media_grid_item_length); 
    mediaItemViewHolder.mediaThumbnail = (ImageView) convertView.findViewById(R.id.iv_media_grid_item_thumbnail); 
    mediaItemViewHolder.cameraItemSelectedView = (RelativeLayout) convertView.findViewById(R.id.rl_item_selection_parent); 
    mediaItemViewHolder.progressContainer = (RelativeLayout) convertView.findViewById(R.id.rl_grid_loader_parent); 
    convertView.setTag(mediaItemViewHolder); 
} else { 
    mediaItemViewHolder = (MediaItemViewHolder)convertView.getTag(); 
    Log.i(TAG, "set blank to "); 
} 

Teraz użyj mediaItemViewHolder.durationTextView.setText(....)

Aktualizacja 1: I zorientowali się problem. Dlaczego lazyloading aktualizuje czas trwania wideo przy złej pozycji gridview. Odrzucić powyżej jeśli chcesz

downloadDuration(resId, durationTextView, mediaItemViewHolder.highlightTagIcon, mediaItemBean); 

jest winowajcą. downloadDuration działa w trybie asynchronicznym i ma wcześniej odniesienie do durationTextView. Załóżmy, że downloadDuration nie jest ukończony i użytkownik przewija numer ListView. Po zakończeniu przewijania ListViewdownloadDuration zostanie zaktualizowana ta durationTextView z wartością, ale dla niewłaściwej pozycji pozycji ListView, a nie dla pozycji, która została przekazana w downloadDuration. Uczynienie z final TextView durationTextView; ostatecznego również nie rozwiąże problemu. Rozwiązaniem może być wyświetlenie pewnego rodzaju pustego wskaźnika na czas i pozwolić, aby downloadDuration zakończył asynchroniczne zadanie. Usuń durationTextView jako parametr i dodaj position jako parametr. Po wykonaniu zadania asynchronicznego można zaktualizować listę komponentów typu MediaItemBean dla tej pozycji. Teraz powiadom adapter, że niektóre wartości zostały zmienione, a ListView zaktualizuje się odpowiednio. Aktualizacja elementu FYIRecyclerView jest bardziej zoptymalizowana niż ListView.

Aktualizacja 2: Możesz pobrać przedmioty z wyprzedzeniem i po prostu zamapować je na fasolę. Zostanie uruchomiony tylko jeden asynchroniczny czas.

Aktualizacja 3: W międzyczasie możesz sprawdzić fasolę dla danego elementu ListView, jeśli ma wartość 0 lub nie. Jeśli jest 0, pokaż w durationTextView.setText("00:00:00") innym wywołaniu downloadDuration i pozwól mu zakończyć i zaktualizować wartość czasu trwania w komponencie bean. Ale nadal musisz notify zaktualizować element.

+0

Próbowałem już tego, myślę, że to nie jest rozwiązanie –

+0

Musisz się pozbyć jeśli (pozycja> = mCameraMediaItems.size()) { Log.d (TAG "Index out of Bound, position:" + position + "- mCameraMediaItems.size():" + mCameraMediaItems.size()); return convertView; } również. Ponieważ jeśli zaimplementowałeś tak jak powyżej, to Index out of Bound, pozycja nie może się zdarzyć. –

+0

ok, robię to samo –

Powiązane problemy