简体   繁体   中英

Multi Downloader With ListView Asynctask

I'm trying to achieve as a downloader app for Android, only that I can not do a thing. I would like to download multiple files at a time and to display the status of under each in a listview.

I created an Adapter and configuring it all, but when I go to download the files first everything works when unloading the second, the first crashes, at least by the idea that, because the data on the listview of the first download are locked. I would like to manage multiple downloads using AsyncTask in a listview. I tried but I can not.

I also created arrays for the variables used in the AsyncTask. If you want to place the pieces of the source. Let me know which part you want.

THis is my ArrayAdapter for Listview:

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;
    }

} This is void 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();

I have a AsyncHttpDownloader library on github, it is a very example to learn http downloads.

What this library does is exactly to manage multiple downloads using AsyncTask. You can have a look at the code.

First step is create an image download callback method and download the image inside your adapter.

    /**
     * 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;
    }

Second step is register a listener on your activity

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

and finally don't forget to unregister the listener on your activity destroy

@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();
}

Writing codes on Stackoverflow is kind of hard huh.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM