您的位置:首页 > 移动开发 > Android开发

Android基础之进程和线程 AsyncTask , Handler

2012-02-27 00:59 435 查看

进程Process

默认情况下,一个应用程序的所有组件都在一个进程之中.

但也可以通过Manifest.xml文件中的android:process来指定某个<activity><service><provider><receiver>控件属于哪个进程,也可以为<application>指定进程

通过android:process可以让同一个应用的组件运行在不同的进程中,也可以使不同应用的组件运行在一个进程中

在系统内存较低的时候,Android系统会按一定规律选择性关闭一些进程.

线程Thread

不要阻塞UI线程(main线程)

不要从UI线程之外的线程来操纵UI,比如imgView.setImageBitmap(...)等

从别的线程来更改UI时,可以用Activity.runOnUiThread(Runnable),View.post(Runnable),View.postDelayed(Runnable,long)

public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}

但遇到更加复杂的情形时会很乱,应该使用一个Handler或者继承AsyncTask类,

AsyncTask异步任务类

继承AsyncTask类时,不用自己去管理线程,onPreExcute是在调用前执行的块,onProgressUpdate,onPostExcute都是在原来的线程中进行的操作

doInBackground是在新的线程中的操作,其返回值返回给了onPostExcute方法

任何时候都可以在doInBackground中使用publishProcess()方法来执行onProgressUpdate.

任何时候都可以取消新线程.

public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
/** The system calls this to perform work in a worker thread and
* delivers it the parameters given to AsyncTask.execute() */
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}

/** The system calls this to perform work in the UI thread and delivers
* the result from doInBackground() */
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}

Handler

Handler的作用
1.可以安排在未来的某时进行一些操作
2.在不同的线程中执行一些操作,并支持线程之间的通信

一个Handler对应着一个线程以及它的消息队列
当你创建一个Handler的时候,它就和创建它的线程/消息队列相绑定
之后,这个handler就要开始处理这个消息队列中的消息了
Looper是一个消息队列的监听器,并不是每一个thread都有looper,主线程在创建时,系统自动为其创建了looper,而用HandlerThread创建的Thread都有looper

可以构建Handler对象与Looper沟通,以便send新消息到messageQueue.
或者接收Looper从MessageQueue中取出的消息.

在子线程中使用主线程的Handler发送消息(向主线程的MessageQueue发送消息)
拿一个常用的功能举例子:比如要从网络上获得一张图片,并且更新到当前Activity的imageView上
首先要新建一个线程,在其run方法中来从网络上下载图片 //下载这种操作比较费时,当然要用异步
在Activity中调用这个线程.start()来启动线程
在线程中下载完成时引用主线程的handler.sendMessage()来通知主线程下载好了开始更新 //在这个功能中handler是主线程的,消息队列也是主线程的,此时的主线程没有必
要有handler和looper,也就没必要用HandlerThread,普通的Thread即可
在主线程的handler中的handleMessage方法中更新UI //handler是主线程的,当然里面的handleMessage方法也在主线程中执行,在UI线程中更新UI
具体实现如下:
在Activity中:
Handler activityHandler=new Handler(){ //因为handler需要重写handlMessage方法来决定其处理消息的方式,要new一个
public void handleMessage(Message msg){
if(msg.arg1==UPDATE_UI){
imageView.setBitmap(....); //如果接受的消息一个参数是UPDATE_UI常量,更新UI
}
}
}

启动一个新的线程:
class ImageThread extends Thread{
public void run(){
//从网络上获得图片
//获得完毕之后
Message msg=new Message(); //生成一个消息对象
msg.arg1=UPDATE_UI; //设置其参数
activityHandler.sendMessage(msg); //调用主线程的activityHandler,向主线程的消息队列发送消息
//或者这里调用
}
}

ImageThread it=new ImageThread();
it.start();

所以如果两个线程之间要相互通信,就要两个线程都拥有handler,looper,消息队列了

而还有handler.post(Runnable) postDelayed(Runnable,long)等,这些线程执行都是在调用它们的handler所在线程执行的

一些简单的实验:
//创建一个Hanlder对象
Handler handler=new Handler();
//把所要进行操作的线程对象用handler.post()或者.postDealyed()方法添加到线程队列中
handler.post(updateThread); //handler.removeCallbacks(updateThread)来从消息队列中去除掉这个线程
Runnable updateThread =new Runnable(){
public void run(){
//线程中的复杂操作
System.out.println("Thread Start");
}
}

//下面这个是可以处理消息的Handler

Handler handler=new Handler(){

public void handleMessage(Message msg){

System.out.println(msg.arg1+"");

}

}

handler.post(updateThread); //把新线程加入到消息队列中

Runnable updateThread=new Runnable(){

public void run(){

Message msg=handler.obtainMessage(); //获得handler中消息队列的一个消息

msg.arg1=50; //为msg携带的值赋值

handler.sendMessage(msg); //把消息加入handler的消息队列

}

}

但是上述两个Handler其实都没有真正的启动另外的线程,而还是在原来的main线程中执行!!!!

如果要使用Handler来生成新线程来执行复杂操作可以使用HandlerThread类,

HandlerThread类会启动一个带有looper的新的线程,而这个looper一会儿可以用来创建Handler

HandlerThread handlerThread=new HandlerThread("handler_thread"); //创建一个HandlerThread线程对象,如果要执行有意义的操作,继承这个类,重写run方法

handlerThread.start();

MyHandler myHandler=new MyHandler(handlerThread.getLooper()); //用新线程的looper来创建一个handler对象

Message msg=myHandler.obtainMessage();

msg.sendToTarget();

class MyHandler extends Handler{

public void handleMessage(Message msg){

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: