取消AsyncTask的内部ListArrayAdapter和辞退通知 [英] Cancel AsyncTask inside ListArrayAdapter and dismiss notification
问题描述
应用程序的目的是提供一个简单的方法来下载并提取了一堆档案(〜200mo),要删除它,打开它。下载显示的显示进度的通知。
我用一个ListView显示每一个可以下载的存档。每个阵列包含一个图像,一些文字,和两个按钮(用于读/删除,下载,或取消)。这些数据来自一个JSON检索。
当我尝试取消其显示通知的AsyncTask并下载文件我有一些问题。当我打电话的 async.cancel(真); 的,通知和下载仍在运行。
也许我是从错误的地方调用AsyncTask的,但我不知道如何解决这个问题。
我的适配器:
公共类ListArrayAdapter扩展ArrayAdapter<串GT; {私人最终上下文的背景下;
公众可绘制D组;
私人的ArrayList<&HashMap的LT;字符串,字符串>>清单;
公共布尔finishDownload = FALSE;
JSONArray jsonArray;//构造
公共ListArrayAdapter(上下文的背景下,列表与LT;弦乐>的价值观,
ArrayList的<&HashMap的LT;字符串,字符串>>名单){
超(背景下,R.layout.activity_list_array_adapter,价值观);
this.context =背景;
this.list =清单;
}@覆盖
公共查看getView(最终诠释的立场,观点convertView,父母的ViewGroup){ LayoutInflater吹气=(LayoutInflater)上下文
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
查看rowView = inflater.inflate(R.layout.activity_list_array_adapter,
父母,假); //声明
TextView的日期=(TextView中)rowView.findViewById(R.id.date);
TextView的标题=(TextView中)rowView.findViewById(R.id.title);
TextView中描述=(TextView中)rowView.findViewById(R.id.description);
ImageView的ImageView的=(ImageView的)rowView.findViewById(R.id.cover);
进度PD =(进度)rowView.findViewById(R.id.progress);
最终按钮按钮1 =(按钮)rowView.findViewById(R.id.button1);
最后的按钮按钮2 =(按钮)rowView.findViewById(R.id.button2); //装满JSON文件数组
title.setText(list.get(位置)获得(标题));
date.setText(list.get(位置)获得(日期));
description.setText(list.get(位置)获得(说明));
新ParseImage(位置,ImageView的,PD).execute(); 最终文件的文件=新的文件(Environment.getExternalStorageDirectory()
.getPath()+/杂志/+ list.get(位置)获得(姓名)+.ZIP); //如果文件存在,让用户打开它
如果(file.exists()){
button1.setText(里拉);
button2.setVisibility(View.VISIBLE);
button2.setText(Supprimer);
} //否则,让用户下载
其他{
button1.setText(Télécharger);
button2.setVisibility(View.GONE);
} 最后DownloadTask异步=新DownloadTask(上下文,位置,清单); button1.setOnClickListener(新Button.OnClickListener(){
@覆盖
公共无效的onClick(视图v){
如果(button1.getText()==Télécharger){
button1.setEnabled(假);
button2.setVisibility(View.VISIBLE);
button2.setText(更改或取消);
finishDownload = FALSE;
async.execute(0);
}否则如果(button1.getText()==里拉){
意图I1 =新意图(背景下,WebActivity.class);
context.startActivity(I1);
}
}
}); button2.setOnClickListener(新Button.OnClickListener(){
@覆盖
公共无效的onClick(视图v){
如果(button2.getText()==更改或取消){
async.cancel(真);
button1.setEnabled(真);
button2.setVisibility(View.GONE);
button1.setText(Télécharger);
}否则如果(button2.getText()==Supprimer){
button1.setEnabled(真);
button2.setVisibility(View.GONE);
button1.setText(Télécharger); 如果(file.exists()){
file.delete();
}
}
}
}); 返回rowView;
}公共类DownloadTask扩展的AsyncTask<整数,整数,太虚> { 私人NotificationHelper mNotificationHelper;
公众诠释的位置;
公众的ArrayList<&HashMap的LT;字符串,字符串>>清单; 公共DownloadTask(上下文的背景下,INT位置,
ArrayList的<&HashMap的LT;字符串,字符串>>名单){
mNotificationHelper =新NotificationHelper(背景);
this.position =位置;
this.list =清单;
} @覆盖
在preExecute保护无效(){
mNotificationHelper.createNotification();
} @覆盖
保护无效doInBackground(整数...整数){
诠释计数= 0;
尝试{
视频下载(1);
网址URL =新的URL(list.get(位置)获得(内容));
URLConnection的连接如= url.openConnection();
conection.connect();
INT lenghtOfFile = conection.getContentLength(); 输入的InputStream =新的BufferedInputStream(url.openStream()
8192); OutputStream的输出=新的FileOutputStream(环境
.getExternalStorageDirectory()的getPath()
+/杂志/
+ list.get(位置)获得(姓名)
+的.zip); 字节的数据[] =新的字节[1024]; 总长= 0;
INT progress_temp = 0;
而((计数= input.read(数据))!= - 1)
{
总+ =计数;
progress_temp =(int)的总* 100 / lenghtOfFile;
output.write(数据0,计);
} publishProgress(progress_temp);
output.flush();
output.close();
input.close(); }赶上(例外五){
Log.e(错误,e.getMessage());
}
返回null;
} @覆盖
保护无效onProgressUpdate(整数...进度){
mNotificationHelper.progressUpdate(进展[0]);
} @覆盖
保护无效onCancelled(){
mNotificationHelper.completed(); super.onCancelled();
} @覆盖
保护无效onPostExecute(虚空结果){ mNotificationHelper.completed(); finishDownload = TRUE;
}
}
}
该notificationHelper类管理的通知:
公共类NotificationHelper {
私人语境mContext;
私人INT NOTIFICATION_ID = 1;
私人通知mNotification;
私人NotificationManager mNotificationManager;
私人的PendingIntent mContentIntent;
私人CharSequence的mContentTitle; 公共NotificationHelper(上下文的背景下){
mContext =背景;
} @燮pressWarnings(德precation)
公共无效createNotification(){
mNotificationManager =(NotificationManager)mContext
.getSystemService(Context.NOTIFICATION_SERVICE); INT图标= android.R.drawable.stat_sys_download;
CharSequence的tickerText = mContext.getString(R.string.download_ticker);
时长= System.currentTimeMillis的();
mNotification =新的通知(图标,tickerText时); mContentTitle = mContext.getString(R.string.content_title);
的CharSequence contentText =0%téléchargé; 意图notificationIntent =新意图(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);
} @燮pressWarnings(德precation)
公共无效progressUpdate(INT percentageComplete){
CharSequence的contentText = percentageComplete +%téléchargé; mNotification.setLatestEventInfo(mContext,mContentTitle,contentText,
mContentIntent);
mNotificationManager.notify(NOTIFICATION_ID,mNotification);
} 公共无效完成(){
mNotificationManager.cancel(NOTIFICATION_ID);
}
}
的取消()
在 AsyncTasks
方法(容易混淆)实际上并没有停止运行线程,而是设置一个标志的任务。你可以在这里找到有关一些讨论。如此看来,目前,如果你想你的线程真正停止中旬执行,你需要使用手动检查标志在你的循环code中的 isCancelled()
方法。例如,在doInBackground while循环
,而((数= input.read(数据))!= -1)
{
总+ =计数;
progress_temp =(int)的总* 100 / lenghtOfFile;
output.write(数据0,计);
如果(isCancelled())
{
// code在这里,可能...
//跳出循环,
//停止线程,
//关闭通知,
//执行任何清理,等等。
}
}
下可以找到用法这在AsyncTask的文档另一个例子头。希望这有助于!
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);
}
}
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!
这篇关于取消AsyncTask的内部ListArrayAdapter和辞退通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!