每个人的一生都有许多梦想,但如果其中一个不断搅扰着你,剩下的就仅仅是行动了。
本讲内容:AsyncTask类
不过为了更加方便我们在子线程对UI进行操作,Android还提供了一个AsyncTask异步任务工具类。
一、构建AsyncTask子类的参数
AsyncTask<Params,Progress,Result>是一个抽象类,通常用于被继承,继承AsyncTask需要指定如下三个泛型参数:
Params: 启动任务时输入参数的类型。
Progress:后台任务执行中返回进度值的类型。
Result: 后台执行任务完成后返回结果的类型。
二、构建AsyncTask子类的回调方法
1、doInBackground:必须重写,异步执行后台线程将要完成的任务,通常完成耗时操作(只有该方法在子线程运程的)。
2、onPreExecute:执行后台耗时操作前被调用,通常用户完成一些初始化操作。
3、onPostExecute:当doInBackground()方法完成后,系统会自动调用onPostExecute()方法,并将
doInBackground()方法返回的值传给该方法。
4、onProgressUpdate:在doInBackground()方法中调用publishProgress()方法更新任务的执行进度后,就会触发该方法。
三、AsyncTask注意事项:
必须在UI线程中创建AsyncTask的实例
必须在UI线程中调用AsyncTask的execute()方法
重写的四个方法是系统自动调用的,不允许手动调用
每个AsyncTask只能被执行一次,多次调用将会引发异常
示例一:
下面是MyAsyncTask.java文件:
public class MyAsyncTask extends AsyncTask<Void, Void, Void>{
protected Void doInBackground(Void... params) {
Log.d("MainActivity", "doInBackground");
publishProgress();//传入进度值(第二个参数)
return null;
}
protected void onPreExecute() {
super.onPreExecute();
Log.d("MainActivity", "onPreExecute");
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Log.d("MainActivity", "onPostExecute");
}
protected void onProgressUpdate(Void... values) {//获取进度,更新进度条
super.onProgressUpdate(values);
Log.d("MainActivity", "onProgressUpdate");
}
}
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyAsyncTask task=new MyAsyncTask();
task.execute();//启动task
}
}
运行程序打印:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Image Test"
android:onClick="loadImage" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp" >
<ImageView
android:id="@+id/id_image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ProgressBar
android:id="@+id/id_proBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone" />
</RelativeLayout>
public class ImageTest extends Activity{
private ImageView image;
private ProgressBar groBar;
private static String URL="http://www.sinaimg.cn/dy/slidenews/4_img/2015_19/704_1622466_277302.jpg";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image);
image=(ImageView) findViewById(R.id.id_image);
groBar=(ProgressBar) findViewById(R.id.id_proBar);
new MyAsyncTask().execute(URL);
}
//<url类型,进度值类型,返回值类型>
class MyAsyncTask extends AsyncTask<String, Void, Bitmap>{
InputStream is;
BufferedInputStream bis;
protected void onPreExecute() {
super.onPreExecute();
groBar.setVisibility(View.VISIBLE);
}
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
groBar.setVisibility(View.GONE);
image.setImageBitmap(result);
}
//... 可变长数组,
protected Bitmap doInBackground(String... params) {
//获取传入的参数
String url=params[0];
Bitmap bitmap=null;
URLConnection connection;//定义网络连接对象
try {
connection=new URL(url).openConnection();//获取网络连接对象
is=connection.getInputStream();
bis=new BufferedInputStream(is);
//通过decodeStream()解析输入流成bitmap
bitmap=BitmapFactory.decodeStream(bis);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
is.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//将bitmap作为参数返回
return bitmap;
}
}
}
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void loadImage(View v){
Intent intent=new Intent(this,ImageTest.class);
startActivity(intent);
}
}
声明网络权限
<uses-permission android:name="android.permission.INTERNET" />
示例三:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Progress Test"
android:onClick="loadProgress" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp">
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/id_progressBar"
android:layout_centerInParent="true"/>
</RelativeLayout>
下面是ProgressBarTest .java界面文件 :
public class ProgressBarTest extends Activity{
private ProgressBar mProgressBar;
private MyAsyncTask mTask;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progressbar);
mProgressBar=(ProgressBar) findViewById(R.id.id_progressBar);
mTask=new MyAsyncTask();
mTask.execute();
}
//因为我们必须要等一个线程结束后才可以操作其它操作,防止我们中途退出,又进入出现等待线程结束才开始执行情况
protected void onPause() {
super.onPause();
if(mTask!=null&&mTask.getStatus()==AsyncTask.Status.RUNNING){
//cancel()方法只是将对应的AsyncTask标记为cancel状态,并不是真正的取消线程的执行。
mTask.cancel(true);//取消AsyncTask
}
}
class MyAsyncTask extends AsyncTask<Void, Integer, Void>{
protected Void doInBackground(Void... params) {
for(int i=0;i<100;i++){
if(isCancelled()){
break;
}
publishProgress(i);
try {//模拟整个进度栏的更新
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if(isCancelled()){
return;
}
//因为只传入一个参数,所以获取下标为0的参数,获取进度更新值
mProgressBar.setProgress(values[0]);
}
}
}
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void loadProgress(View v){
Intent intent=new Intent(this,ProgressBarTest.class);
startActivity(intent);
}
}