android - 取消 ListArrayAdapter 内的 AsyncTask 并关闭通知

标签 android android-asynctask android-arrayadapter android-notifications

该应用程序的目的是提供一种简单的方法来下载和提取一堆文件(~200mo)、删除它并打开它。下载会显示一条通知,显示进度。

我使用 ListView 来显示每个可以下载的存档。每个数组包含一个图像、一些文本和两个按钮(用于读取/删除、下载或取消)。数据是从 json 中检索的。

我在尝试取消显示通知并下载文件的 AsyncTask 时遇到了一些问题。当我调用 async.cancel(true); 时,通知和下载仍在运行。

也许我从错误的地方调用了 asyncTask,但我不知道如何解决这个问题。

我的适配器:

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

管理通知的 notificationHelper 类:

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

最佳答案

AsyncTasks 上的 cancel() 方法(令人困惑)实际上并没有停止线程的运行,而是在任务上设置了一个标志。你可以找到一些关于这个的讨论here 。目前看来,如果您希望线程实际上在执行中停止,则需要使用 isCancelled() 方法手动检查循环代码中的该标志。例如,在 doInBackground 的 while 循环中:

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 。希望这有帮助!

关于android - 取消 ListArrayAdapter 内的 AsyncTask 并关闭通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16611184/

相关文章:

Android:如果最初的 Activity 不是从启动器启动的,则通知开始新 Activity 而不是恢复旧 Activity

php - 未从 Android POST 接收 PHP 参数

android - 错误异步任务 doInBackground() & JSoup

java - 无法更新卡中显示的值 - Android 的 Cardslib 库

android - 自定义 ArrayAdapter getView 未被调用——为什么不呢?

android - 如何为 AutoCompleteTextView 创建自定义 BaseAdapter

java - 仅在 android 的自定义 ListView 中搜索特定值的结果?

java - 安卓/MySQL : how can I display data based on the department associated with the logged-in user?

android - 菜单中的图标未在android中显示

android - 自定义操作 Intent 在与我从中单击的应用程序相同的上下文中打开我的应用程序