Android 理解多线程
安卓应用程序通常是应用在一个单独的线程里的,即为主线程,用于显示用户界面以及响应用户的操作。
如果一些耗时任务也同时在主线程里去完成,则会影响用户体验,会阻塞UI主线程。我们会创建一个单独的线程或者子线程,去处理这些耗时操作(如网络请求、数据库操作等)。
那么这些子线程就是AsyncTask、Thread、HandlerThread,它们叫做安卓的工作者线程。
- AsyncTask
- Handler
一、AsyncTask异步任务
AsyncTask是Android的一个轻量级异步类,可以自定义类并继承AsyncTask,实现异步任务处理操作。并且AsyncTask提供了接口返回异步操作的进度,最后会返回结果到UI主线程中。
优点:简单快捷,过程可以控制
缺点:在处理多个异步操作时比较复杂
参数 | 说明 |
---|---|
Params | 启动任务时输入的执行参数,一般为一个网络地址 |
Progress | 异步任务执行的进度 |
Result | 异步任务执行后的结果的类型 |
代码实例
这是一个利用AsyncTask加载网络图片的代码:
public class MainActivity extends ActionBarActivity
{
private Button button1;
private ImageView imageview1;
private ProgressDialog dialog;private String image_uri =”https://imgsa.baidu.com/baike/c0%3Dbaike272%2C5%2C5%2C272%2C90/sign=c4f298bb97ef76c6c4dff379fc7f969f/9358d109b3de9c82f077b3156b81800a19d8431d.jpg”;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dialog = new ProgressDialog(this);
dialog.setTitle(“图片下载”);
dialog.setMessage(“正在下载,请稍后…”);
button1 = (Button) findViewById(R.id.button1);
imageview1 = (ImageView) findViewById(R.id.imageView1);
button1.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
new DownloadTask().execute(image_uri);
}
});
}
//自定义下载类继承AsyncTask
public class DownloadTask extends AsyncTask<String, Void, Bitmap>
{
// 这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。
@Override
protected void onPreExecute()
{
// TODO Auto-generated method stub
dialog.show();
super.onPreExecute();
}
// 这个方法中的所有代码都会在子线程中运行,主要完成耗时任务
// 注意,在这个方法中是不可以进行UI操作的
//在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。
@Override
protected Bitmap doInBackground(String... params)
{
// TODO Auto-generated method stub
// 使用网络链接类HttpClient完成网络数据的获取
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(params[0]);
Bitmap bitmap = null;
try
{
HttpResponse httpResponse = httpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode() == 200)
{
HttpEntity httpEntity = httpResponse.getEntity();
byte[] data = EntityUtils.toByteArray(httpEntity);
bitmap = BitmapFactory
.decodeByteArray(data, 0, data.length);
}
} catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}
return bitmap;
}
//在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。
@Override
protected void onProgressUpdate(Void... values)
{
// TODO Auto-generated method stub
super.onProgressUpdate(values);
}
// 可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果,以及关闭掉进度条对话框等。
protected void onPostExecute(Bitmap result)
{
// TODO Auto-generated method stub
super.onPostExecute(result);
imageview1.setImageBitmap(result);
dialog.dismiss();
}
}
}
参考:android AsyncTask介绍
详解Android中AsyncTask的使用
二、Handler
1、Handler概念:
I 、Handler 是 Android 给我们提供来更新 UI 的一套机制,也是一套消息处理的机制,我们可以发送消息,也可以通过它来处理消息。
II、Android 在设计的时候,就封装了一套消息创建、传递、处理机制,如果不遵循这样的机制就没有办法更新 UI 信息,就会抛出异常信息。
2、与Handler相关的几个概念:
I、Message 消息,理解为线程间通讯的数据单元。例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程。
II、Message Queue 消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
III、Handler Handler是Message的主要处理者,负责将Message添加到消息队列以及对消息队列中的Message进行处理。
Looper 循环器,扮演Message Queue和Handler之间桥梁的角色,循环取出Message Queue里面的Message,并交付给相应的Handler进行处理。
IV、线程 UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。
3、Handler的一些分发消息的方法
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
4、关于Message
创建Handler实例,要重载handleMessage方法,来处理消息
获取Message对象的最好方法是调用Message.obtain()
Message可传递的参数:
①. arg1 arg2 整数类型,是setData的低成本替代品,传递简单类型。
Object 类型 obj
②. what 用户自定义的消息代码,这样接受者可以了解这个消息的信息。每个handler各自包含自己的消息代码,所以不用担心自定义的消息跟其他handlers有冲突
③.其他的可以通过Bundle进行传递
Message可以通过new Message构造来创建一个新的Message,但是这种方式很不好,不建议使用。最好使用Message.obtain()来获取Message实例,它创建了消息池来处理的。
5、代码实例
利用Handler创建一个dialog进度条并显示进度
public class HandlerActivity extends Activity
{
private Button button1;
private static ProgressDialog dialog;
//创建Handler静态对象
private static Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
int index=msg.arg1;
dialog.setProgress(index);
if (msg.what==1)
{
dialog.dismiss();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
button1=(Button)findViewById(R.id.button1);
dialog=new ProgressDialog(this);
dialog.setTitle(“正在下载…”);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
button1.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
new Thread(new MyThread()).start();
dialog.show();
}
});
}
//创建一个子线程继承Runnable
public class MyThread implements Runnable{
int count=1;
int index=0;
@Override
public void run()
{
// TODO Auto-generated method stub
while(count<=100){
try
{
Thread.sleep(200);
} catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}
Message message=Message.obtain();
message.arg1=count;
handler.sendMessage(message);
count++;
}
Message end=Message.obtain();
end.what=1;
handler.sendMessage(end);
}
}