I created a gridview that displays videos from the server. GridItem has high resolution video and video duration. To load the thumb, I use UniversalImageloader and load the video duration by creating lazyloading using asynctask.Lazyloading works fine. but if someone scrolls the gridview, then the duration of the video is shown in the wrong position. to create lazyloading i'm below link
@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); } }