Cancel AsyncTask inside ListArrayAdapter and dismi

2019-07-20 10:52发布

The aim of the application is to offer a simple way to download and extract a bunch of archives (~200mo), to delete it, and to open it. The download display a notification which display the progress.

I'm using a ListView to display every archive that can be downloaded. Each array contain an image, some text, and two buttons (for reading/deleting, downloading, or cancel). The data are retrieved from a json.

I've got some issues while I try to cancel the AsyncTask which display the notification and download the file. When I call the async.cancel(true);, the notification and the download are still running.

Maybe am I calling the asyncTask from the wrong place, but I don't know how to fix this.

My adapter :

public class ListArrayAdapter extends ArrayAdapter<String> {

private final Context context;
public Drawable d;
private ArrayList<HashMap<String, String>> list;
public boolean finishDownload = false;
JSONArray jsonArray;

// Constructor
public ListArrayAdapter(Context context, List<String> values,
        ArrayList<HashMap<String, String>> list) {
    super(context, R.layout.activity_list_array_adapter, values);
    this.context = context;
    this.list = list;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.activity_list_array_adapter,
            parent, false);

    // Déclaration
    TextView date           = (TextView) rowView.findViewById(R.id.date);
    TextView title          = (TextView) rowView.findViewById(R.id.title);
    TextView description    = (TextView) rowView.findViewById(R.id.description);
    ImageView imageView     = (ImageView) rowView.findViewById(R.id.cover);
    ProgressBar pd          = (ProgressBar) rowView.findViewById(R.id.progress);
    final Button button1    = (Button) rowView.findViewById(R.id.button1);
    final Button button2    = (Button) rowView.findViewById(R.id.button2);

    // Fill the array with the json file
    title.setText(list.get(position).get("Title"));
    date.setText(list.get(position).get("Date"));
    description.setText(list.get(position).get("Description"));
    new ParseImage(position, imageView, pd).execute();

    final File file = new File(Environment.getExternalStorageDirectory()
            .getPath() + "/Magazine/"   + list.get(position).get("Name") + ".zip");

    //If the file exist, let the user open it
    if (file.exists()) {
        button1.setText("Lire");
        button2.setVisibility(View.VISIBLE);
        button2.setText("Supprimer");
    } 

    // else, let the user download it
    else {
        button1.setText("Télécharger");
        button2.setVisibility(View.GONE);
    }

    final DownloadTask async = new DownloadTask(context, position, list);

    button1.setOnClickListener(new Button.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (button1.getText() == "Télécharger") {
                button1.setEnabled(false);
                button2.setVisibility(View.VISIBLE);
                button2.setText("Annuler");
                finishDownload = false;
                async.execute(0);
            } else if (button1.getText() == "Lire") {
                Intent i1 = new Intent(context, WebActivity.class);
                context.startActivity(i1);
            }
        }
    });

    button2.setOnClickListener(new Button.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (button2.getText() == "Annuler") {
                async.cancel(true);
                button1.setEnabled(true);
                button2.setVisibility(View.GONE);
                button1.setText("Télécharger");
            } else if (button2.getText() == "Supprimer") {
                button1.setEnabled(true);
                button2.setVisibility(View.GONE);
                button1.setText("Télécharger");

                if (file.exists()) {
                    file.delete();
                }
            }
        }
    });

    return rowView;
}

public class DownloadTask extends AsyncTask<Integer, Integer, Void> {

    private NotificationHelper mNotificationHelper;
    public int position;
    public ArrayList<HashMap<String, String>> list;

    public DownloadTask(Context context, int position,
            ArrayList<HashMap<String, String>> list) {
        mNotificationHelper = new NotificationHelper(context);
        this.position = position;
        this.list = list;
    }

    @Override
    protected void onPreExecute() {
        mNotificationHelper.createNotification();
    }

    @Override
    protected Void doInBackground(Integer... integers) {
        int count = 0;
        try {
            Thread.sleep(1);
            URL url = new URL(list.get(position).get("Content"));
            URLConnection conection = url.openConnection();
            conection.connect();
            int lenghtOfFile = conection.getContentLength();

            InputStream input = new BufferedInputStream(url.openStream(),
                    8192);

            OutputStream output = new FileOutputStream(Environment
                    .getExternalStorageDirectory().getPath()
                    + "/Magazine/"
                    + list.get(position).get("Name")
                    + ".zip");

            byte data[] = new byte[1024];

            long total = 0;
            int progress_temp = 0;


            while ((count=input.read(data)) != -1)
            {
                total += count;
                progress_temp = (int) total*100/lenghtOfFile;
                output.write(data, 0, count);
            }

            publishProgress(progress_temp);
            output.flush();
            output.close();
            input.close();

        } catch (Exception e) {
            Log.e("Error: ", e.getMessage());
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        mNotificationHelper.progressUpdate(progress[0]);
    }

    @Override
    protected void onCancelled() {
        mNotificationHelper.completed();

        super.onCancelled();
    }

    @Override
    protected void onPostExecute(Void result) {

        mNotificationHelper.completed();

        finishDownload = true;
    }
}
}

The notificationHelper class which manage the notification :

public class NotificationHelper {
    private Context mContext;
    private int NOTIFICATION_ID = 1;
    private Notification mNotification;
    private NotificationManager mNotificationManager;
    private PendingIntent mContentIntent;
    private CharSequence mContentTitle;

    public NotificationHelper(Context context) {
        mContext = context;
    }

    @SuppressWarnings("deprecation")
    public void createNotification() {
        mNotificationManager = (NotificationManager) mContext
                .getSystemService(Context.NOTIFICATION_SERVICE);

        int icon = android.R.drawable.stat_sys_download;
        CharSequence tickerText = mContext.getString(R.string.download_ticker);
        long when = System.currentTimeMillis();
        mNotification = new Notification(icon, tickerText, when);

        mContentTitle = mContext.getString(R.string.content_title);
        CharSequence contentText = "0% téléchargé";

        Intent notificationIntent = new Intent(mContext, MainActivity.class);
        mContentIntent = PendingIntent.getActivity(mContext, 0,
                notificationIntent, 0);

        mNotification.setLatestEventInfo(mContext, mContentTitle, contentText,
                mContentIntent);

        mNotification.flags = Notification.FLAG_ONGOING_EVENT;

        mNotificationManager.notify(NOTIFICATION_ID, mNotification);
    }

    @SuppressWarnings("deprecation")
    public void progressUpdate(int percentageComplete) {
        CharSequence contentText = percentageComplete + "% téléchargé";

        mNotification.setLatestEventInfo(mContext, mContentTitle, contentText,
                mContentIntent);
        mNotificationManager.notify(NOTIFICATION_ID, mNotification);
    }

    public void completed() {
        mNotificationManager.cancel(NOTIFICATION_ID);
    }
}

1条回答
做自己的国王
2楼-- · 2019-07-20 11:08

The cancel() method on AsyncTasks (confusingly) doesn't actually stop the Thread from running, but rather sets a flag on the Task. You can find some discussion about that here. It seems that currently, if you want your Thread to actually stop mid-execution, you'll need to manually check that flag in your looping code using the isCancelled() method. For example, in your while loop in doInBackground:

while ((count=input.read(data)) != -1)
{
    total += count;
    progress_temp = (int) total*100/lenghtOfFile;
    output.write(data, 0, count);
    if(isCancelled())
    {
        //Code here that may...
        //    break out of the loop, 
        //    stop the thread, 
        //    close the notification,
        //    perform any cleanup, etc...
    }
}

You can find another example of this in the AsyncTask docs under the "Usage" header. Hope this helps!

查看更多
登录 后发表回答