Android AsyncTask和Thread的行为不同

时间:2014-11-25 16:01:58

标签: android multithreading android-asynctask difference

我发布这个问题是因为我认为这种行为真的很奇怪。

我写了一个AsyncTask来从网上下载文件。这个AsyncTask在一个单独的类中声明,所以我可以从任何地方调用它。我注意到在AsyncTask执行期间我的应用程序反应非常缓慢,这很奇怪,因为根据定义,AsyncTask的{​​{1}}方法应该在一个单独的线程中运行。我真的不明白是什么导致我的应用程序放缓。然后我尝试用线程做同样的事情:PUFFF !!好10倍!!

不应该是一回事吗?有人可以解释一下,为什么使用doInBackground我的应用比使用Thread的响应要快得多?

以下是AsyncTaskThread的实施方式。

通过AsyncTask的这种实现,一旦启动任务,UI就变得无法响应

public class DownloaderTask扩展了AsyncTask {

AsyncTask

使用线程的这种实现,如果完全响应,则使用UI

private Context context;
private PowerManager.WakeLock mWakeLock;
String fileName;

public DownloaderTask(Context context) {
    this.context = context;
}

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

}

@Override
protected String doInBackground(String... sUrl) {
    InputStream input = null;
    OutputStream output = null;
    HttpURLConnection connection = null;
    try {
        URL url = new URL(sUrl[0]);
        connection = (HttpURLConnection) url.openConnection();

        String credentials = "user" + ":" + "password";
        String base64EncodedCredentials = Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
        connection.setRequestMethod("GET");
        connection.addRequestProperty("Authorization", "Basic " + base64EncodedCredentials);
        connection.connect();

        // expect HTTP 200 OK, so we don't mistakenly save error report
        // instead of the file
        if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
            return "Server returned HTTP " + connection.getResponseCode() + " " + connection.getResponseMessage();
        }

        // this will be useful to display download percentage
        // might be -1: server did not report the length
        int fileLength = connection.getContentLength();

        // download the file
        input = connection.getInputStream();
        fileName = url.toString().substring(url.toString().lastIndexOf("/") + 1);
        output = new FileOutputStream(fileName + "_temp");

        byte data[] = new byte[4096];
        long total = 0;
        int count;
        while ((count = input.read(data)) != -1) {
            // allow canceling with back button
            if (isCancelled()) {
                input.close();
                return null;
            }
            total += count;
            // publishing the progress....
            // if (fileLength > 0) // only if total length is known
            // publishProgress((int) (total * 100 / fileLength));
            output.write(data, 0, count);
        }
    } catch (Exception e) {
        return e.toString();
    } finally {
        try {
            if (output != null)
                output.close();
            if (input != null)
                input.close();
        } catch (IOException ignored) {
        }

        if (connection != null)
            connection.disconnect();
    }
    return null;
}

@Override
protected void onPostExecute(String result) {
    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context).setSmallIcon(R.drawable.ic_launcher).setContentTitle("File downloaded").setContentText("The requested files have been downloaded").setAutoCancel(true);
    // Creates an explicit intent for an Activity in your app
    Intent resultIntent = new Intent();
    resultIntent.setAction(Intent.ACTION_VIEW);
    resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    File file = new File(fileName + "_temp");
    file.renameTo(new File(fileName));
    file = new File(fileName);
    Uri uri = Uri.fromFile(file);

    resultIntent.setData(uri);

    PendingIntent contentIntent = PendingIntent.getActivity(context, 0, resultIntent, 0);
    mBuilder.setContentIntent(contentIntent);
    NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    // mId allows you to update the notification later on.
    mNotificationManager.notify(1, mBuilder.build());

    if (result != null)
        Toast.makeText(context, "Download error: " + result, Toast.LENGTH_LONG).show();
    else
        Toast.makeText(context, "File downloaded", Toast.LENGTH_SHORT).show();
}

2 个答案:

答案 0 :(得分:2)

不确定,但我打赌问题是您可能会明确调用AsyncTask.doInBackground()而不是使用AsyncTask.execute()方法。

调用doInBackground()显式绕过整个asyncTask机制,并在调用它的同一个线程上执行代码(在你的情况下可能是UI主thrad)。

更多信息:http://developer.android.com/reference/android/os/AsyncTask.html

答案 1 :(得分:0)

从Honeycomb 3.0开始,AsyncTasks任务在单个线程上执行,以避免因并行执行而导致的常见应用程序错误。

因此,如果您同时运行多个任务,则一次只能运行一个任务。

如果您想运行并行任务,则需要使用

executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);