Android ListView和适配器
我正在处理一个下载管理器项目,因此,为了显示所有下载/下载操作,我更喜欢使用ListView显示我的下载列表。假设我们有多达个下载任务,那么所有任务的进度条都必须更新。对于后台下载任务,我创建了一个新类,并将其命名为Android ListView和适配器,android,listview,Android,Listview,我正在处理一个下载管理器项目,因此,为了显示所有下载/下载操作,我更喜欢使用ListView显示我的下载列表。假设我们有多达个下载任务,那么所有任务的进度条都必须更新。对于后台下载任务,我创建了一个新类,并将其命名为HttpDownloader。所以,我在这个类的对象上传递这些进度条。当一个新对象添加到我的任务列表中时,我调用HttpDownloader的构造函数,并将新项目进度条传递给它。让我困惑的是当我向tasklist添加一个新对象并调用adapter的notifyDataSetChang
HttpDownloader
。所以,我在这个类的对象上传递这些进度条。当一个新对象添加到我的任务列表中时,我调用HttpDownloader
的构造函数,并将新项目进度条传递给它。让我困惑的是当我向tasklist添加一个新对象并调用adapter的notifyDataSetChanged时,我的列表被刷新,所以所有进度条都重置为默认布局值,但HTTPDownloader线程在后台成功运行。
所以,我的问题是
1。调用notifyDataSetChanged后,对旧listview对象的引用是析构函数?
2。如果是,如何保留旧视图的引用?
3。如果否,请向我解释,当后台进程强制通过progressbar更改进度值时,为什么进度条重置为默认值而不更改?
HTTPDownloader类
适配器类
class MyAdapter扩展了ArrayAdapter{
ArrayList M_列表;
公共MyAdapter(ArrayList列表){
超级(MainActivity.this,R.layout.download_项目,列表);
此.M_列表=列表;
}
@凌驾
public int getCount(){
返回此.M_list.size();
}
公共视图getView(int位置、视图转换视图、视图组父视图){
LayoutFlater充气机=(LayoutFlater)getSystemService(布局充气机服务);
视图行视图=充气机。充气(R.layout.download_项,父项,false);
ProgressBar=(ProgressBar)rowView.findViewById(R.id.progrees);
新线程(新的HttpDownloader(this.M_list.get(position),bar)).start();
返回行视图;
}
}
当调用notifyDataSetChanged()或Activity resumes时,列表的每一行都会调用适配器的getView()方法
因此,当您向列表中添加新项并调用notifyDataSetChanged()时,getView()方法的执行次数与该时刻列表中的项的执行次数相同,另外还有一个原因导致您添加了新项
正如您所知,getView()方法构建行,因此构建一个新的ProgressBar,显然,这个ProgressBar从progress的位置0开始
因此,答案可以恢复为“是”,每次调用notifyDataSetChanged(),getView()方法都会被多次调用,每行调用一个(如果您将android:layout_height参数设置为0dip,android:layou weight设置为1.0,就像您可能知道的ListView),这就是为什么您会得到ProgressBars“初始化”的原因当您将新项目添加到ListView时。如果您想保留引用以显示良好的下载管理器,请按部分查看如何操作 这个概念很容易理解,我们有线程下载项目,我们将调用每一项工作任务。每个任务都与列表视图中的一行相关联,因为您希望显示每个项目下载的下载进度 所以,如果每个任务都与每一行相关联,我们将保存实际上正在执行的任务,通过这种方式,我们随时都知道正在运行的任务及其状态。这一点很重要,因为正如我前面所说的,getView()方法被多次调用,我们需要知道每个正在进行的下载及其状态 让我们看看适配器的一些代码:
class MyAdapter extends ArrayAdapter<Uri> {
ArrayList<Uri> M_list;
Map<Uri, HttpDownloader> taskMap;
public MyAdapter(ArrayList<Uri> list) {
super(MainActivity.this, R.layout.download_item, list);
this.M_list = list;
taskMap = new HashMap<Uri, HttpDownloader>();
}
@Override
public int getCount() {
return this.M_list.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.download_item, parent, false);
ProgressBar progressBar = (ProgressBar) rowView.findViewById(R.id.progressBar);
configureRowWithTask(position, progressBar);
return rowView;
}
private void configureRowWithTask(int position,final ProgressBar bar) {
Uri url = M_list.get(position);
HttpDownloader task;
if (!(taskMapHasTaskWithUrl(url))) {
task = new HttpDownloader(url, bar);
Thread thread = new Thread(task);
thread.start();
taskMap.put(url, task);
} else {
task = taskMap.get(url);
bar.setProgress(task.getProgress());
task.setProgressBar(bar);
}
}
private boolean taskMapHasTaskWithUrl(Uri url) {
if (url != null) {
Iterator taskMapIterator = taskMap.entrySet().iterator();
while(taskMapIterator.hasNext()) {
Map.Entry<Uri, HttpDownloader> entry = (Map.Entry<Uri, HttpDownloader>) taskMapIterator.next();
if (entry.getKey().toString().equalsIgnoreCase(url.toString())) {
return true;
}
}
}
return false;
}
}
这个类基本上是相同的,不同之处在于我在UI线程中使用了一个处理程序来更改进度条的进度,并且仅当对进度条的引用不为null时才更改这个进度
重要的是每次下载字节时,下载进度的值都会刷新
我已经在测试应用程序中检查了代码,似乎所有的运行都正常,如果您有一些问题,请告诉我,我会尽力帮助您;)
希望您能理解。我想保留这些参考资料。调用
notifyDataSetChanged()
时,可以更改所有旧引用。我想保留这些参考资料,我怎么能保留这个?(我正在使用ListView编程下载管理器UI,我们应该更改所有progressbars的值)
class MyAdapter extends ArrayAdapter<String> {
ArrayList<String> M_list;
public MyAdapter(ArrayList<String> list) {
super(MainActivity.this, R.layout.download_item, list);
this.M_list = list;
}
@Override
public int getCount() {
return this.M_list.size();
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.download_item, parent, false);
ProgressBar bar = (ProgressBar) rowView.findViewById(R.id.progrees);
new Thread (new HttpDownloader(this.M_list.get(position), bar)).start();
return rowView;
}
}
class MyAdapter extends ArrayAdapter<Uri> {
ArrayList<Uri> M_list;
Map<Uri, HttpDownloader> taskMap;
public MyAdapter(ArrayList<Uri> list) {
super(MainActivity.this, R.layout.download_item, list);
this.M_list = list;
taskMap = new HashMap<Uri, HttpDownloader>();
}
@Override
public int getCount() {
return this.M_list.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.download_item, parent, false);
ProgressBar progressBar = (ProgressBar) rowView.findViewById(R.id.progressBar);
configureRowWithTask(position, progressBar);
return rowView;
}
private void configureRowWithTask(int position,final ProgressBar bar) {
Uri url = M_list.get(position);
HttpDownloader task;
if (!(taskMapHasTaskWithUrl(url))) {
task = new HttpDownloader(url, bar);
Thread thread = new Thread(task);
thread.start();
taskMap.put(url, task);
} else {
task = taskMap.get(url);
bar.setProgress(task.getProgress());
task.setProgressBar(bar);
}
}
private boolean taskMapHasTaskWithUrl(Uri url) {
if (url != null) {
Iterator taskMapIterator = taskMap.entrySet().iterator();
while(taskMapIterator.hasNext()) {
Map.Entry<Uri, HttpDownloader> entry = (Map.Entry<Uri, HttpDownloader>) taskMapIterator.next();
if (entry.getKey().toString().equalsIgnoreCase(url.toString())) {
return true;
}
}
}
return false;
}
}
public class HttpDownloader implements Runnable {
private Uri url;
private ProgressBar progressBar;
private int progress = 0;
private Handler handler;
public HttpDownloader (Uri url, ProgressBar progressBar) {
this.url = url;
this.progressBar = progressBar;
progressBar.setProgress(progress);
handler = new Handler();
}
@Override
public void run() {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url.toString());
HttpResponse response;
try {
response = client.execute(get);
InputStream is = response.getEntity().getContent();
long contentLength = response.getEntity().getContentLength();
int downloadedLen = 0;
int readBytes = 0;
byte [] buffer = new byte [1024];
while ((readBytes = is.read(buffer, 0, buffer.length)) != -1) {
downloadedLen += readBytes;
//Some storing to file codes
progress = (int) ((100f * downloadedLen) / contentLength);
handler.post(new Runnable() {
@Override
public void run() {
if (progressBar != null) {
progressBar.setProgress(progress);
}
}
});
}
} catch (ClientProtocolException e) {
Log.e("HttpDownloader", "Error while getting response");
} catch (IOException e) {
e.printStackTrace();
Log.e("HttpDownloader", "Error while reading stream");
}
}
public int getProgress() {
return progress;
}
public void setProgressBar(ProgressBar progressBar) {
this.progressBar = progressBar;
}
}