我将简单列表视图编写为下载列表,用户可以单击该列表进行下载。我没有任何问题从互联网下载服务,但在列表视图项目上的可见进度条后。这显示整个列表视图,我无法处理,不显示整个列表视图,只显示点击列表浏览项目的进度条下载。
我的适配器:
public void fillItems(final AdapterMessageContent adapter, final MessagesList item, final int position) {
stream_url = item.getStream_link().split("/");
stream_filename = stream_url[stream_url.length - 1];
File file = new File(G.dir_image + "/" + stream_filename);
if (item.getMsg_type() != 0) {
if (!file.exist()) {
Log.e("", "visible downloader icon");
UI.imgv_image_item.setImageBitmap(BitmapFactory.decodeFile(G.dir_app + "/" + "thumbs/" + item.getPreview_image_url()));
/* SET tag to handle this listview item */
UI.npb_progressbar.setTag(item.getId());
UI.iv_download_icon.setVisibility(View.VISIBLE);
UI.iv_download_icon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
UI.ll_handle_progress_bar.setVisibility(View.VISIBLE);
item.setDownload_status(1);
G.DOWNLOADLIST.create(new DownloadTaskList(item.getMsg_id(), 0, item.getStream_link(), 0, 0, 0, position));
G.context.startService(new Intent(G.currentActivity, ServiceMultiTaskDownloader.class).putExtra("download_item_id", item.getMsg_id()));
UI.npb_progressbar.setVisibility(View.VISIBLE);
UI.tv_downloding_file_info.setVisibility(View.VISIBLE);
}
});
} if (UI.npb_progressbar.getTag().equals(item.getId())) {
UI.imgv_image_item.setImageBitmap(BitmapFactory.decodeFile(G.dir_app + "/" + item.getPreview_image_url()));
/* HIDE icon to disable click by user to download file */
UI.iv_download_icon.setVisibility(View.INVISIBLE);
}
}
}
现在这个适配器我可以通过简单的BroadCastReceiver更新行:
private void updateView(int position, int file_size, int downloaded_size, int percent, String stream_filename) {
View v = UI.lv_message_content.getChildAt(position - UI.lv_message_content.getFirstVisiblePosition());
UI.lv_message_content.getAdapter().getView(position, v, UI.lv_message_content);
UI.lv_message_content.invalidateViews();
if (v == null) return;
ImageView imgv_image_item = (ImageView) v.findViewById(R.id.imgv_image_item);
NumberProgressBar numberProgressBar = (NumberProgressBar) v.findViewById(R.id.npb_progressbar);
TextView tv_downloding_file_info = (TextView) v.findViewById(R.id.tv_downloding_file_info);
if (numberProgressBar.getTag() != null && numberProgressBar.getTag().equals(messagesLists.get(position).getId())) {
numberProgressBar.setProgress(percent);
tv_downloding_file_info.setVisibility(View.VISIBLE);
tv_downloding_file_info.setText(UC.convertByteToMB(downloaded_size) + "/" + UC.convertByteToMB(file_size));
if (percent == 100) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 30;
Bitmap bmp = BitmapFactory.decodeFile(G.dir_image + "/" + stream_filename);
imgv_image_item.setImageBitmap(bmp);
tv_downloding_file_info.setVisibility(View.GONE);
numberProgressBar.setVisibility(View.GONE);
}
}
}
不幸的是,当点击UI.iv_download_icon
下载文件时,我的列表视图项目在位置0和位置6重复。
答案 0 :(得分:0)
如果我理解这一点并仔细阅读代码,我认为这是一个误解Adapters
和ListView
(或RecyclerView
)工作原理的案例。
ListView
和新的RecyclerView
回收他们显示的视图,以便最大限度地减少内存占用和查看创建开销。为了使列表中有数百个视图,他们使用Adapters
创建一些视图(足以填充列表所占用的区域),然后更新视图的内容,因为它是显示项目的时间给用户。
如果绕过Adapter
的逻辑并修改属于Adapter
的视图的内容,则会对列表中上下的看似随机的项目进行相同的更改发生回收。
解决此问题的方法是使用getView
(或Adapter
onBindViewHolder
)的RecyclerView.Adapter
方法进行视图更新。 Adapter
应该有一个内部数据列表,您可以使用它来决定视图的外观。然后,您可以修改数据并调用notifyDataSetChanged
(使用RecyclerView.Adapter
时还有其他选项),这会导致为需要更新的每个项目调用getView
(在屏幕上可见)
故事的道德:永远不要直接查看列表中的视图更新,而是修改Adapter
中的数据,并通知它数据已更改,因此它知道应该查看更新以显示最新数据。