在Android中实现异步任务机制有两种方式,Handler和AsyncTask。
Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制。上篇做了一个关于Handler模式下的下载,感兴趣的可以看下。关于Handler的相关知识可参考下这篇博文http://blog.csdn.net/liuhe688/article/details/6407225别人写的很不错。
为了简化操作,Android1.5提供了工具类android.os.AsyncTask,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务。
在使用AsyncTask的时候,有几点需要格外注意:
1.异步任务的实例必须在UI线程中创建。
2.execute(Params... params)方法必须在UI线程中调用。
3.不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。
4.不能在doInBackground(Params... params)中更改UI组件的信息。
5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。
下面上代码:新手有不足之处多多指出
Activity代码
package com.wu;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;
public class AndroidTestActivity extends Activity {
/** Called when the activity is first created. */
private ProgressDialog pd = null;
private ProgressBar pb;
private float fileSize;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
download = (Button) findViewById(R.id.second);
download.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//注意每次需new一个实例,新建的任务只能执行一次,否则会出现异常
MyTask mTask = new MyTask();
download.setEnabled(false);
pd = new ProgressDialog(AndroidTestActivity.this);
pd.setTitle("上传中");
pd.setMessage("文件共"+fileSize/1024/1024+"M");
pd.show();
mTask.execute("http://music.baidu.com/data/music/file?link=http://zhangmenshiting.baidu.com/data2/music/106150597/10090002354000128.mp3?xcode=56ea6c3d5f9b569dfbe9ff93fd6d8248075fef7b4684889d&song_id=100900023");
}
});
pb = (ProgressBar) findViewById(R.id.progress_bar);
}
private class MyTask extends AsyncTask<String, Integer, String>{
//onPreExecute方法用于在执行后台任务前做一些UI操作
@Override
protected void onPreExecute() {
};
/* (non-Javadoc)
* @see doInBackground方法内部执行后台任务,不可在此方法内修改UI
*/
@Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
InputStream is = null;
OutputStream os = null;
//在SD卡创建下载目录
String sdpath = Environment.getExternalStorageDirectory()+"/down/";
File f = new File(sdpath);
try {
//如果文件夹不再则创建
if(!f.exists()){
f.mkdir();
}
URL url = new URL(params[0]);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(6*1000);
conn.connect();
is = conn.getInputStream();
os = new FileOutputStream(sdpath+"asd.mp3");
//获得文件长度
fileSize = conn.getContentLength();
byte buffer[] = new byte[512];
int count = 0;
int length = -1;
while ((length = is.read(buffer)) != -1) {
os.write(buffer, 0, length);
count += length;
//调用publishProgress公布进度,最后onProgressUpdate方法将被执行
publishProgress((int) ((count / fileSize) * 100));
os.flush();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try{
os.close();
is.close();
}
catch(Exception e){
e.printStackTrace();
}
}
return null;
}
/* (non-Javadoc)
* onProgressUpdate方法用于更新进度信息)
*/
@Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
//设置进度条进度
pb.setProgress(values[0]);
pd.setMessage("文件共"+fileSize/1024/1024+"M"+"已下载"+values[0].toString()+"%");
}
/* (non-Javadoc)
* onPostExecute方法用于在执行完后台任务后更新UI,显示结果
*/
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
download.setEnabled(true);
//消失弹出框
pd.dismiss();
}
//onCancelled方法用于在取消执行中的任务时更改UI
@Override
protected void onCancelled() {
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="second"
android:id="@+id/second"/>
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:progress="0"
android:max="100"
style="?android:attr/progressBarStyleHorizontal"/>
</LinearLayout>
注意在配置文件中添加相关的权限。