首先撇清一个概念:Android的单线程设计是指每个应用程序的UI线程(主线程)是单线程的,即和用户交互的界面是单线程的。但是,很显然,用户界面如果采用多线程处理效率会更高,Android为什么将UI线程限制为单线程呢?这是为了避免并发编程的复杂性,也是提高Android应用的健壮性的有效途径。

但是,主线程是单线程的,并不等于Android不支持多线程,比如两个Android应用程序之间的通讯。

Android中的Handler提供了线程之间通讯的简便手段,如下图所示:

android 单线程执行任务 安卓单线程_ide

Android的主线程(即UI线程)内部实现了消息队列机制,即一个主线程会自动创建一个消息队列(显然也只有一个消息队列),同时创建一个读取消息队列的Looper对象。主线程的所有用户交互都通过消息队列和Looper对象来实现:当有新的消息进入消息队列时,Looper会及时读取消息并调用相应的处理逻辑(更新用户界面)。

当其他线程希望更新用户界面时,可以通过Handler提供的sendMessage方法在消息队列中放入一个消息(Message对象,可以携带大量信息),这样Looper即可以及时获取该消息,并调用Handler相应的handleMessage方法处理该消息,这样就实现了线程之间的通讯。由此可以看出,Handler在线程通讯中起到了一个枢纽作用:Handler即负责和消息队列打交道,也负责处理相应的消息,其他线程通过Handler和主线程通讯,就可以不需要考虑和主线程的竞争和同步问题,极大的简化了线程的使用。

下面的示例代码演示了一个每隔1秒显示一条消息在主界面:

public class MainActivity extends Activity {
private TextView label;
private static int UPDATE = 1;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
label.setText(String.valueOf(msg.obj));
super.handleMessage(msg);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
label = (TextView) findViewById(R.id.label);
new Thread() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Message msg = new Message();
msg.what = UPDATE;
msg.obj = "当前循环变量:" + i;
handler.sendMessage(msg);
}
}
}.start();
}
}
publicclassMainActivityextendsActivity{
privateTextViewlabel;
privatestaticintUPDATE=1;
privateHandlerhandler=newHandler(){
@Override
publicvoidhandleMessage(Messagemsg){
if(msg.what==1){
label.setText(String.valueOf(msg.obj));
super.handleMessage(msg);
}
}
};
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
label=(TextView)findViewById(R.id.label);
newThread(){
@Override
publicvoidrun(){
for(inti=0;i<100;i++){
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
// TODO Auto-generated catch block
e.printStackTrace();
}
Messagemsg=newMessage();
msg.what=UPDATE;
msg.obj="当前循环变量:"+i;
handler.sendMessage(msg);
}
}
}.start();
}
}

在上面的例子中,所谓的其他线程其实主线程的子线程,下面一个例子则演示了完全不同的两个组件通过Handler实现的交互:一个Service每隔1秒产生一个随机数,然后在主线程显示出来:

ServiceDemo.java文件:

public class ServiceDemo extends Service {
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
private Thread workThread;
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "(1) onCreate()",
Toast.LENGTH_LONG).show();
workThread = new Thread(null,backgroudWork,"WorkThread");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(this, "(2) onStart()",
Toast.LENGTH_SHORT).show();
if (!workThread.isAlive()){
workThread.start();
}
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "(3) onDestroy()",
Toast.LENGTH_SHORT).show();
workThread.interrupt();
}
private Runnable backgroudWork = new Runnable(){
@Override
public void run() {
try {
while(!Thread.interrupted()){
double randomDouble = Math.random();
MainActivity.updateGUI(randomDouble);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}


publicclassServiceDemoextendsService{
@Override
publicIBinderonBind(Intentarg0){
// TODO Auto-generated method stub
returnnull;
}
privateThreadworkThread;
@Override
publicvoidonCreate(){
super.onCreate();
Toast.makeText(this,"(1) onCreate()",
Toast.LENGTH_LONG).show();
workThread=newThread(null,backgroudWork,"WorkThread");
}
@Override
publicvoidonStart(Intentintent,intstartId){
super.onStart(intent,startId);
Toast.makeText(this,"(2) onStart()",
Toast.LENGTH_SHORT).show();
if(!workThread.isAlive()){
workThread.start();
}
}
@Override
publicvoidonDestroy(){
super.onDestroy();
Toast.makeText(this,"(3) onDestroy()",
Toast.LENGTH_SHORT).show();
workThread.interrupt();
}
privateRunnablebackgroudWork=newRunnable(){
@Override
publicvoidrun(){
try{
while(!Thread.interrupted()){
doublerandomDouble=Math.random();
MainActivity.updateGUI(randomDouble);
Thread.sleep(1000);
}
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
};
}
MainActivity.java文件:
public class MainActivity extends Activity {
private static TextView label;
private static int UPDATE = 1;
protected static Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
label.setText(String.valueOf(msg.obj));
super.handleMessage(msg);
}
}
};
public static void updateGUI(double doubleRadom){
Message msg = new Message();
msg.what = UPDATE;
msg.obj = "当前随机数:" + doubleRadom;
handler.sendMessage(msg);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
label = (TextView) findViewById(R.id.label);
final Intent serviceIntent = new Intent(this, ServiceDemo.class);
startService(serviceIntent);
}
}


publicclassMainActivityextendsActivity{
privatestaticTextViewlabel;
privatestaticintUPDATE=1;
protectedstaticHandlerhandler=newHandler(){
@Override
publicvoidhandleMessage(Messagemsg){
if(msg.what==1){
label.setText(String.valueOf(msg.obj));
super.handleMessage(msg);
}
}
};
publicstaticvoidupdateGUI(doubledoubleRadom){
Messagemsg=newMessage();
msg.what=UPDATE;
msg.obj="当前随机数:"+doubleRadom;
handler.sendMessage(msg);
}
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
label=(TextView)findViewById(R.id.label);
finalIntentserviceIntent=newIntent(this,ServiceDemo.class);
startService(serviceIntent);
}
}

可以看出,为了实现在两个组件间的通讯,主要的变化是:

将Handler对象定义为static类型的,便于在其他组件访问handler

在主线程中实现一个静态的updateGUI方法,以便通过调用handler.sendMessage添加一个消息到消息队列中

在Service的线程中,调用主线程的updateGUI并传入适当的参数

Handler和消息循环机制的设计很巧妙,在WEB应用和企业级应用中是否可以借鉴呢?

android 单线程执行任务 安卓单线程_主线程_02

0