如何在android中的onCancelled()方法上完成AsyncTask

时间:2016-06-25 09:08:56

标签: android android-asynctask nullpointerexception activity-finish

我正在尝试完成我的AsyncTask,名为 DownloadSong ,同时取消Asynctask,但它会将nullPointerException视为错误。如何在 onCancelled()上完成Asynctask。

public class DownloadSong extends AsyncTask<String, Integer, String> {

Context context;
Activity activity;
public static String songName, songURL;

private NotificationHelper mNotificationHelper;
public static int notificationID = 1;
boolean download = false;

DownloadSong asynk;

public DownloadSong()
{
    this.activity=activity;
}

public DownloadSong(Activity activity, String songName, String songURL) {
    this.activity = activity;
    this.songName = songName;
    this.songURL = songURL;

    mNotificationHelper = new NotificationHelper(activity, songName);
}

@Override
protected void onPreExecute() {
    super.onPreExecute();

    notificationID++;
    mNotificationHelper.createNotification(notificationID);
}

@Override
protected String doInBackground(String... file_URL) {

    try {
        URL url = new URL(songURL);
        HttpURLConnection URLconnection = (HttpURLConnection) url.openConnection();
        URLconnection.setRequestMethod("GET");
        URLconnection.setDoOutput(true);
        URLconnection.connect();

        // Detect the file length
        int fileLength = URLconnection.getContentLength();

        File fSDcard = Environment.getExternalStorageDirectory();
        String strSdcardPath = fSDcard.getAbsolutePath();

        File fDirectory = new File(strSdcardPath + "/GSD");

        if (!fDirectory.exists()) {
            fDirectory.mkdir();
        }

        File fMyFile = new File(fDirectory.getAbsolutePath() + "/" + songName + ".mp3");
        Log.e("Download file name ", fMyFile.toString());

        FileOutputStream out = new FileOutputStream(fMyFile, true);

        InputStream input_File = URLconnection.getInputStream();

        byte[] data = new byte[1024];
        int total = 0;
        int count;

        while ((count = input_File.read(data)) != -1 && !isCancelled()) {

            total += count;
            publishProgress((int) (total * 100 / fileLength));

            out.write(data, 0, count);
        }

        out.flush();
        out.close();
        input_File.close();

    } catch (IOException e) {

        Log.e("Download Error : ", "Failed");
    }
    Log.e("Download status", " Complete ");

    return null;
}

@Override
protected void onPostExecute(String s) {

    if (download) {

        mNotificationHelper.clearNotification();

        Toast.makeText(activity, "Could Not Connect to Server.", Toast.LENGTH_LONG).show();
        Log.e("download","could not connect to server");
    } else {

        mNotificationHelper.completed();
        try {
            Toast.makeText(activity, "Song " + "'" + songName + "'" + " downloaded successfully", Toast.LENGTH_LONG).show();
        }catch (Exception e)
        {
            Toast.makeText(activity, "Song downloaded successfully", Toast.LENGTH_LONG).show();
        }
        Log.e("download", "completed");
    }
}

@Override
protected void onProgressUpdate(Integer... progress) {

    mNotificationHelper.progressUpdate(progress[0]);
    super.onProgressUpdate(progress);
}

@Override
protected void onCancelled() {
    super.onCancelled();
    asynk.activity.finish();
}}

从BroadcastReceiver取消asynctask

public class CancelDownloadReceiver extends BroadcastReceiver {

Context context;
DownloadSong asynk;
NotificationHelper manage;
Activity activity;

public CancelDownloadReceiver() {
}

@Override
public void onReceive(Context context, Intent intent) {

    int notificationId = intent.getIntExtra("notificationId", 0);
    Log.e("Notification ID ",notificationId+"");

    NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    manager.cancel(notificationId);

    asynk=new DownloadSong(activity);
    Log.e("Activity",activity+"");
    asynk.cancel(true);

    Toast.makeText(context,"Download cancelled.",Toast.LENGTH_LONG).show();}

但它会给出致命错误,如下所示:

Process: com.dnk.gsd, PID: 31934
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Activity.finish()' on a null object reference
at com.dnk.gsd.DownloadSong.onCancelled(DownloadSong.java:144)
at android.os.AsyncTask.onCancelled(AsyncTask.java:405)
at android.os.AsyncTask.finish(AsyncTask.java:630)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5576)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:956)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:751)

1 个答案:

答案 0 :(得分:2)

nullPointerException的问题不是因为你取消了AsyncTask,而是因为你试图完成调用者活动。在AsyncTask完成其进程之前,您的活动可能会被销毁。所以,改为使用

Q4:

更改为:

Activity activity;

然后在你的构造函数中改为:

WeakReference<Activity> activityWeakRef;

然后您可以使用以下方式获取活动:

public DownloadSong(Activity activity, String songName, String songURL) {
    this.activityWeakRef = new WeakReference<>(activity);
    this.songName = songName;
    this.songURL = songURL;

    mNotificationHelper = new NotificationHelper(activity, songName);
}

在你的onCancelled()中:

activityWeakRef.get();

以下更改将避免您从泄漏活动和nullPointerException。

- 更新 -

您可以阅读以下有关杀死AsyncTask的问答:

How to completely kill/remove/delete/stop an AsyncTask in Android

- 新更新 -

要确保您的活动不为空,请务必检查它。改为:

@Override
protected void onCancelled() {
    activityWeakRef.get().finish();
    super.onCancelled();

}

- 新的更新 - 请记住将默认的contstructor设置为private并删除其中的活动初始化。从以下代码:

@Override
protected void onCancelled() {
  if(activityWeakRef.get() != null) {
     activityWeakRef.get().finish();
  }
  super.onCancelled();
}

public DownloadSong()
{
    this.activity=activity;
}

这将确保您在不初始化活动的情况下不会意外创建新的AsyncTask。