带有 ListView Asynctask 的多下载器

Posted

技术标签:

【中文标题】带有 ListView Asynctask 的多下载器【英文标题】:Multi Downloader With ListView Asynctask 【发布时间】:2013-09-10 20:32:37 【问题描述】:

我正在努力实现作为 android 的下载器应用程序,只是我无能为力。我想一次下载多个文件并在列表视图中显示每个文件的状态。

我创建了一个适配器并对其进行了全部配置,但是当我首先下载文件时,卸载第二个文件时一切正常,第一个崩溃,至少是这样的想法,因为第一次下载的列表视图上的数据是锁定。我想在列表视图中使用 AsyncTask 管理多个下载。我试过了,但我做不到。

我还为 AsyncTask 中使用的变量创建了数组。 如果要放置源的碎片。让我知道你想要哪一部分。

这是我的 Listview ArrayAdapter:

public class MYArrayAdapter extends ArrayAdapter<String>

    //riferimenti statici alle risorse e agli id
    private final static int LAYOUT = R.layout.item_view;
    private final static int IMMAGINE = R.id.ColImgPath;
    private final static int NAMEFILE = R.id.txt_namef;
    private final static int VELOCITA = R.id.txt_velocita;
    private final static int TIME = R.id.txt_timerima;
    private final static int DIMTOT = R.id.txt_dimtota;
    private final static int DIMRIM = R.id.txt_dimrim;
    private final static int PERCENTUALE = R.id.txt_percent;
    private final static int Progress = R.id.prg_progressbar;
    //private final static int TITOLO = R.id.riga_listview_titolo;
    //private final static int DESCRIZIONE = R.id.riga_listview_descrizione;

    //ArrayList<String> IMMAGINE; //lista dei titoli
    ArrayList<String> namefile;
    ArrayList<String> velocita;
    ArrayList<String> time;
    ArrayList<String> dimtot;
    ArrayList<String> dimrim;
    ArrayList<String> percentuale;
    ArrayList<String> percento;
    //ArrayList<String> descrizioni;
    //lista delle descrizioni

    Context c; //context
    LayoutInflater inflater; //layout inflater

    public MYArrayAdapter(Context context, ArrayList<String> namefile, ArrayList<String> velocita,ArrayList<String> time,ArrayList<String> dimtot,ArrayList<String> dimrim,ArrayList<String> percentuale)
    
        super(context,NAMEFILE);
        this.c = context;
        this.namefile = namefile;
        this.velocita = velocita;
        this.time = time;
        this.dimtot = dimtot;
        this.dimrim = dimrim;
        this.percentuale = percentuale;
        this.percento = percento;
        this.inflater = LayoutInflater.from(c);
    

    @Override
    public int getCount()
    
        return namefile.size(); //ritorno lunghezza lista ( = numero dei titoli)
    

    //quando la lista richiede una view
    @Override
    public View getView(int pos,View view,ViewGroup parent)
    
        CacheRiga cache; //cache
        if(view==null)//se � la prima volta che viene richiesta la view
        
            // creo la view ma non l'attacco alla lista in quanto devo ancora modificare
            // i testi delle textview
            view = inflater.inflate(LAYOUT, parent,false); 
            cache = new CacheRiga(); //inizializzo la cache
            cache.namefile = (TextView) view.findViewById(NAMEFILE);
            cache.velocita = (TextView) view.findViewById(VELOCITA);
            cache.time = (TextView) view.findViewById(TIME);
            cache.dimtot = (TextView) view.findViewById(DIMTOT);
            cache.dimrim = (TextView) view.findViewById(DIMRIM);
            cache.percentuale = (TextView) view.findViewById(PERCENTUALE);
            cache.immagine = (ImageView) view.findViewById(IMMAGINE);
            cache.progress = (ProgressBar) view.findViewById(Progress);
            view.setTag(cache);//collego view con cache
        
        else
        
            cache = (CacheRiga) view.getTag(); //altrimenti prendo la cache dalla view
        

        cache.namefile.setText(namefile.get(pos)); //imposto il titolo
        cache.velocita.setText(velocita.get(pos)); // e la descrizione
        cache.time.setText(time.get(pos)); //imposto il titolo
        cache.dimtot.setText(dimtot.get(pos)); // e la descrizione
        cache.dimrim.setText(dimrim.get(pos)); //imposto il titolo
        cache.percentuale.setText(percentuale.get(pos)); // e la descrizione
        cache.immagine.setImageResource(R.drawable.file); //imposto il titolo
        cache.progress.setProgress((int) Tab_Download.progresso[pos]); // e la descrizione

        return view;
    

    private class CacheRiga  // classe per la cache delle righe
        public TextView namefile; // cache titolo
        public TextView velocita; // cache descrizione
        public TextView time; // cache titolo
        public TextView dimtot;
        public TextView dimrim; // cache titolo
        public TextView percentuale;
        public ImageView immagine; // cache titolo
        public ProgressBar progress;
    

这是无效的 onProgressUpdate (AsyncTask):

speed[cont] = NANOS_PER_SECOND / BYTES_PER_MIB * totalRead[cont] / (System.nanoTime() -  start[cont] + 1);
    dimrim[cont] = ((((file_sizes[cont] * 1024) * 1024) - ((int) (totalRead[cont]))) / 1024) / 1024;
    timerimas[cont] = (int) ((dimrim[cont] ) / speed[cont]);
    ore[cont] = timerimas[cont] / 3600;
    minuti[cont] = (timerimas[cont] % 3600) / 60;
    secondi[cont] = timerimas[cont] - (ore[cont] * 3600) - (minuti[cont] * 60);


    progresso[cont] =  (totalRead[cont] * 100) / lenghtOfFile[cont];

    velocita.set(cont,"Velocita' Download:" + df.format(speed[cont]) + "Mbyte/s");
    namefile.set(cont,"Nome File:"+file_name[cont]);
    time.set(cont,"Tempo Rimanente:"+ore[cont]+"H| "+ minuti[cont] +"M| " + secondi[cont]+"S ");
    dimtot.set(cont,"Dimensione file:"+(file_sizes[cont]) + "MB");
    dimrimas.set(cont,"Dimensione Rimanente:" + dimrim[cont] + "MB");
    percentuale.set(cont, "Percentuale:" + progresso[cont] + "%");

    //list.setAdapter(adapter);
    adapter.notifyDataSetChanged();

【问题讨论】:

请发布一些代码,以及崩溃日志。 它不会崩溃,但我在 listview 上看不到 2 下载信息! 【参考方案1】:

我在github上有一个AsyncHttpDownloader库,非常适合学习http下载。

这个库所做的正是使用 AsyncTask 管理多个下载。你可以看看代码。

第一步是创建一个图片下载回调方法并在你的适配器中下载图片。

    /**
     * This code is to update the progress bar in the listView
     * @param view
     * @param downloadUrl
     * @param total
     * @param progress
     */
    public void updateDownloadProgress(View view, String downloadUrl, int total, int progress)
        ViewHolder viewHolder = (ViewHolder)view.getTag();
        DataItem dataItem = dataList.get(viewHolder.position);

        // If the download urls not match, will not continue.
        if (!dataItem.imageUrl.equals(downloadUrl)) return;
        viewHolder.progressBar.setMax(total);
        viewHolder.progressBar.setProgress(progress);
    

    /**
     * This code is to call to set the image to the view from the activity.
     * @param view
     * @param fileUrl
     */
    public void setImageViewWhenDownloadFinished(View view, String downloadUrl, String fileUrl)
        ViewHolder viewHolder = (ViewHolder)view.getTag();

        // If the download urls not match, will not continue.
        if (!dataItem.imageUrl.equals(downloadUrl)) return;

        Bitmap bmp = BitmapFactory.decodeFile(fileUrl);
        viewHolder.imageView.setImageBitmap(bmp);
    

    @Override
    public View getView(int position, View view, ViewGroup viewGroup) 
        // TODO Auto-generated method stub
        ViewHolder viewHolder;
        if (view == null)
            view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.example_layout, null);
            viewHolder = new ViewHolder();
            viewHolder.imageView = (ImageView)view.findViewById(R.id.imageView);
            viewHolder.progressBar = (ProgressBar)view.findViewById(R.id.progressBar);
        view.setTag(viewHolder);
        else
            viewHolder = (ViewHolder)view.getTag();
        

        viewHolder.position = position;
        DataItem dataItem = dataList.get(position);

        // Download the image file
        AsyncHttpDownloader.getInstance().addDownloadTask(this, dataItem.imageUrl);

        return view;
    

第二步是在你的活动上注册一个监听器

//Instantiate a new listener
AsyncHttpDownloaderListener downloaderListener = new AsyncHttpDownloaderListener(
    new AsyncHttpDownloaderListener.Callback() 

    @Override
    public void onProgressUpdate(String downloadUrl, int total, int completed) 
        // Update to progress bar
        for (int i = 0; i < listView.getChildCount(); i++)
            adapter.updateDownloadProgress(listView.getChildAt(i), downloadUrl, total, completed);
        
    

    @Override
    public void onFailed(String downloadUrl, String errorMessage) 

    

    @Override
    public void onSuccess(String downloadUrl, File file) 
        //When the download finished, the assign the image to the imageView
        for (int i = 0; i < listView.getChildCount(); i++)
            adapter.setImageViewWhenDownloadFinished(listView.getChildAt(i), file.getAbsolutePath());
        
    
);

@Override
public void onCreate(Bundle savedInstanceState)
    super.onCreate(savedInstanceState);
    downloaderListener.register(this);

最后不要忘记取消注册您的活动销毁的监听器

@Override
public void onDestroy()
    downloaderListener.unregister(this);

    // When the activity is destroyed, cancel all running tasks if you want.
    // If you don't cancel, it will run in the background until all tasks are
    // done, when you open the activity again, you can still see the running task.
    AsyncHttpDownloader.getInstance().cancelAllRunningTasks();

    super.onDestroy();

在 *** 上写代码有点难啊。

【讨论】:

以上是关于带有 ListView Asynctask 的多下载器的主要内容,如果未能解决你的问题,请参考以下文章

AsyncTask 完成后 ListView 上的 setOnItemClickListener

即使 Activity 已销毁,AsyncTask 也不会停止

在 asynctask 类中设置为 listView

ListView 未在 AsyncTask 中使用适配器进行更新

使用 AsyncTask 在 ListView 中加载图片

从两个不同的 AsyncTask 更新一个 ListView