- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我创建了一个 gridview,它显示来自服务器的视频。 GridItem 有视频缩略图和视频持续时间。为了加载视频的缩略图,我正在使用 UniversalImageloader 并通过使用 asynctask 创建延迟加载来加载视频持续时间。延迟加载工作正常。但如果有人频繁滚动 gridview,则视频持续时间显示在错误的位置。为了创建延迟加载,我在下面关注 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);
}
}
最佳答案
摆脱 view
并使用 convertView
从方法中接收。改成如下
//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 ");
}
现在使用 mediaItemViewHolder.durationTextView.setText(....)
更新 1: 我已经找到问题所在了。 为什么延迟加载会在错误的 gridview 位置更新视频持续时间。 如果需要,请丢弃以上内容
downloadDuration(resId, durationTextView, mediaItemViewHolder.highlightTagIcon, mediaItemBean);
是罪魁祸首。 downloadDuration
以异步模式运行,并且它事先有 durationTextView
的引用。假设 downloadDuration
未完成并且用户滚动 ListView
。滚动 ListView
downloadDuration
完成后,此 durationTextView
将更新为错误的 ListView
值项目位置,而不是这是在 downloadDuration
中传递的位置。制作 final TextView durationTextView;
final 也解决不了问题。解决方案可能是显示某种持续时间的空指示器,并让 downloadDuration
完成它的异步作业。删除 durationTextView
作为参数并添加 position
作为参数。异步作业完成后,您可以为该位置更新 MediaItemBean
类型的 bean 列表。现在通知适配器某些值已更改,ListView
将相应地更新自身。 仅供引用 RecyclerView
项目更新比 ListView
更优化。
更新 2:您可以提前获取项目并将其映射到 bean。只会运行一次异步。
更新 3:与此同时,您可以检查特定 ListView
项的 bean 是否为 0。如果在 durationTextView.setText("00:00:00")
中显示为 0,则调用 downloadDuration
并让它完成并更新 bean 中的持续时间值。但是您仍然需要通知
更新项目。
关于android - Textview 延迟加载,setText 在 gridview 中的错误位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42297658/
我已经使用 vue-cli 两个星期了,直到今天一切正常。我在本地建立这个项目。 https://drive.google.com/open?id=0BwGw1zyyKjW7S3RYWXRaX24tQ
您好,我正在尝试使用 python 库 pytesseract 从图像中提取文本。请找到代码: from PIL import Image from pytesseract import image_
我的错误 /usr/bin/ld: errno: TLS definition in /lib/libc.so.6 section .tbss mismatches non-TLS reference
我已经训练了一个模型,我正在尝试使用 predict函数但它返回以下错误。 Error in contrasts<-(*tmp*, value = contr.funs[1 + isOF[nn]])
根据Microsoft DataConnectors的信息我想通过 this ODBC driver 创建一个从 PowerBi 到 PostgreSQL 的连接器使用直接查询。我重用了 Micros
我已经为 SoundManagement 创建了一个包,其中有一个扩展 MediaPlayer 的类。我希望全局控制这个变量。这是我的代码: package soundmanagement; impo
我在Heroku上部署了一个应用程序。我正在使用免费服务。 我经常收到以下错误消息。 PG::Error: ERROR: out of memory 如果刷新浏览器,就可以了。但是随后,它又随机发生
我正在运行 LAMP 服务器,这个 .htaccess 给我一个 500 错误。其作用是过滤关键字并重定向到相应的域名。 Options +FollowSymLinks RewriteEngine
我有两个驱动器 A 和 B。使用 python 脚本,我在“A”驱动器中创建一些文件,并运行 powerscript,该脚本以 1 秒的间隔将驱动器 A 中的所有文件复制到驱动器 B。 我在 powe
下面的函数一直返回这个错误信息。我认为可能是 double_precision 字段类型导致了这种情况,我尝试使用 CAST,但要么不是这样,要么我没有做对...帮助? 这是错误: ERROR: i
这个问题已经有答案了: Syntax error due to using a reserved word as a table or column name in MySQL (1 个回答) 已关闭
我的数据库有这个小问题。 我创建了一个表“articoli”,其中包含商品的品牌、型号和价格。 每篇文章都由一个 id (ID_ARTICOLO)` 定义,它是一个自动递增字段。 好吧,现在当我尝试插
我是新来的。我目前正在 DeVry 在线学习中级 C++ 编程。我们正在使用 C++ Primer Plus 这本书,到目前为止我一直做得很好。我的老师最近向我们扔了一个曲线球。我目前的任务是这样的:
这个问题在这里已经有了答案: What is an undefined reference/unresolved external symbol error and how do I fix it?
我的网站中有一段代码有问题;此错误仅发生在 Internet Explorer 7 中。 我没有在这里发布我所有的 HTML/CSS 标记,而是发布了网站的一个版本 here . 如您所见,我在列中有
如果尝试在 USB 设备上构建 node.js 应用程序时在我的树莓派上使用 npm 时遇到一些问题。 package.json 看起来像这样: { "name" : "node-todo",
在 Python 中,您有 None单例,在某些情况下表现得很奇怪: >>> a = None >>> type(a) >>> isinstance(a,None) Traceback (most
这是我的 build.gradle (Module:app) 文件: apply plugin: 'com.android.application' android { compileSdkV
我是 android 的新手,我的项目刚才编译和运行正常,但在我尝试实现抽屉导航后,它给了我这个错误 FAILURE: Build failed with an exception. What wen
谁能解释一下?我想我正在做一些非常愚蠢的事情,并且急切地等待着启蒙。 我得到这个输出: phpversion() == 7.2.25-1+0~20191128.32+debian8~1.gbp108
我是一名优秀的程序员,十分优秀!