第五章 进程与线程
进程:一个应用程序就是一个进程
(1)进程的优先级:
Foreground Process 前台进程
a. 当前用户正在操作的Activity所在的进程
b. 绑定了当前用户操作的Activity的service所在的进程
c. 通过调用了startForeground()方法提升优先级的service所在的进程
d. 正在调用onCreate()、onStart()、onDestory()方法的service所在的进程
e. 正在调用onReceiver()方法的BroadcastReceiver所在的进
Visiable Process 可见进程
a. 处于暂停状态的Activity所在的进程
b. 绑定了处于暂停状态的Activity的service所在的进程
Service Process 服务进程
通过调用startService()方法启动的service所在的进程
Background Process 后台进程
处于停止状态的Activity所在的进程
Empty Process 空进程
加速下一个程序的启动
线程;一个程序内部的顺序控制流
ANR:Application Not Responding 应用程序未响应
主线程机制:当main线程执行耗时超过5秒,没有响应下一事件,可能出现ANR
main线程的作用:UI的创建、更新、事件的处理
Only the original thread that created a view hierarchy can touch its views
只有创建了该控件的线程才能去更新这个控件
Handler消息传递机制:实现在新创建的线程中操作UI界面
(1)MessageQueue消息队列:
MessageQueue用于存放Message,存放的Message按照FIFO(先进先出)的原则执行。MessageQueue被封装到Looper里面
(2)Looper循环者
在Android中,一个线程对应一个Looper对象,一个Looper对象对应一个MessageQueue。Looper对象用来为一个线程开启一个消息循环,用来操作MessageQueue。默认情况下,Android新创建的线程是没有开启消息循环的(主线程除外)。要想在非主线程中创建Handler对象,首先需要用Looper类的prepare()方法初始化一个Looper对象,然后创建Handler对象,再使用Looper类的loop()方法,启动Looper,从消息队列里获取和处理消息。例如:
public class LooperThread extends Thread{
public Handler handler;
@Override
public void run(){
super.run();
Looper.prepare();
//实例化一个Handler对象
handler = new Handler(){
public void handleMessage(Message msg){
Log.i("Looper",String.valueOf(msg.what));
}
};
Message message = handler.obtainMessage(); //获取消息
message.what = 0x11; //设置Message的what属性的值
handler.sendMessage(message); //发送消息
Looper.loop(); //启动Looper
}
}
Looper类提供的常用方法
a. prepare():用于初始化Looper
b. loop():调用loop()方法后,Looper线程开始真正工作,它会从消息队列里获取消息和处理消息
c. myLooper():可以获取当前线程的Looper对象
d. getThread();用于获取Looper对象所属的线程
e. quit():用于结束Looper循环
备注:写在Looper.loop()之后的代码不会被执行,这个函数内部是一个循环,当调用Handler.getLooper().quit()方法后,loop()方法才会终止,其后面的代码才能得以运行。
(3)Handler消息处理类
Handler允许发送和处理Message或Runnable对象到其所在的线程的MessageQueue中。Handler的主要作用有:
a. 将Message或Runnable应用post()方法或sendMessage()方法发送到MessageQueue中,在发送时可以指定延迟时间、发送时间或要携带的Bundle数据。当MessageQueue循环到该Message时,调用相应的Handler对象的handlerMessage()方法对其进行处理。
b. 在子线程和主线程进行通信,即在工作线程中与UI线程进行通信。
备注:在一个线程中,只能有一个Looper和MessageQueue,但是,可以有多个Handler,且这些Handler可以共享同一个Looper和MessageQueue。
Handler类同的发送和处理消息的常用方法有:
a. handleMessage(Message msg):处理消息的方法。通常重写该方法来处理消息,在发送消息时,该方法会自动回调。
b. post(Runnable r):立即发送Runnable对象,该Runnable对象最后将被封装成Message对象。
c. postAtTime(Runnable r,long uptimeMillis):定时发送Runnable对象
d. postDelayed(Runnable r,long delayMillis):延迟delayMillis毫秒发送Runnable对象
e. sendEmptyMessage(int what):发送空消息
f. sendMessage(Message msg):立即发送消息
g. sendMessageAtTime(Message msg, long uptimeMillis):定时发送消息
h. sendMessageDelayed(Message msg, long delayMillis):延迟多少毫秒发送消息
(4)Message消息类
Message被存放在MessageQueue中,一个MessageQueue中可以包含多个Message对象。每个Message对象可以通过Message.obtain()或者Handler.obtainMessage()方法获得。Message对象具有如下5个属性:
a. arg1:int类型,用来存放整型数据
b. arg2;int类型,用来存放整型数据
c. obj:Object类型,用来存放发送给接收器的Object类型的任意对象
d. replyTo;Messenger类型,用来指定此Message发送到何处的可选Message对象
e. what:int类型,用来指定用户自定义的消息代码,这样接收者可以了解这个消息的信息。
备注;使用Message类的属性可以携带int型数据,如果要携带其他类型的数据,可以先将要携带的数据保存到Bundle对象中,然后通过Message类的setData()方法将其添加到Message中。
注意:
a. 通常情况下,使用Message.obtian()方法或Handler.obtainMessage()方法从消息池中获得空消息对象,以节省资源。
b. 如果一个Message只需携带简单的int型信息,应优先使用Message.arg1和Message.arg2属性来传递信息,这比用Bundle更省内存。
c. 尽可能使用Message.what来标识信息,以便用不同方式处理Message。