Textview Lazyloading, setText in the wrong position in gridview?

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); } } 
+6
source share
1 answer

Get convertView of view and use convertView as you get out of the method. Go to the next

 //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 "); } 

Now use mediaItemViewHolder.durationTextView.setText(....)

Update 1: I found out the problem. Why lazyloading updates the video duration in the wrong grid position. . Cancel it if you want

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

is the culprit. downloadDuration runs asynchronously and has a durationTextView link in hand. Assume downloadDuration not complete and the user scrolls through the ListView . After scrolling the ListView downloadDuration will be completed, then this durationTextView will be updated with the value, but for the wrong position of the ListView position, and not for which position it was transferred to downloadDuration . Creating final TextView durationTextView; as a final also will not solve the problem. The solution may be to show some kind of empty indication for the duration and let downloadDuration shut down async. Remove durationTextView as a parameter and add position as a parameter. After completing the asynchronous job, you can update the bean list of type MediaItemBean for this position. Now tell the adapter that some value has been changed, and the ListView will update it accordingly. FYI RecyclerView element update is more optimized than ListView .

Update 2 . You can preload the elements and simply transfer them to the bean. Only one asynchronous execution is performed.

Update 3 . In the meantime, you can check the bean for a specific ListView if it is 0 or not. If in durationTextView.setText("00:00:00") else the call to downloadDuration displayed 0, and let it end and update the duration value in the bean. But to update an item you need to notify .

+3
source

Source: https://habr.com/ru/post/1015061/


All Articles