我发布这个问题是因为我认为这种行为真的很奇怪。
我写了一个AsyncTask
来从网上下载文件。这个AsyncTask
在一个单独的类中声明,所以我可以从任何地方调用它。我注意到在AsyncTask
执行期间我的应用程序反应非常缓慢,这很奇怪,因为根据定义,AsyncTask
的{{1}}方法应该在一个单独的线程中运行。我真的不明白是什么导致我的应用程序放缓。然后我尝试用线程做同样的事情:PUFFF !!好10倍!!
不应该是一回事吗?有人可以解释一下,为什么使用doInBackground
我的应用比使用Thread
的响应要快得多?
以下是AsyncTask
和Thread
的实施方式。
通过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();
}
答案 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);