您的位置:首页 > 其它

安卓多线程使用总结

2015-07-16 16:01 381 查看

定义梳理

1、Message: Message Queue中的存放的对象。

Message实例对象的取得,通常使用Message类里的静态方法obtain()。它的创建并不一定是直接创建一个新的实例,而是先从Message Pool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。如果Message Pool中没有可用的Message实例,则才用给定的参数创建一个Message对象。

2、MessageQueue:是一种 数据 结构,是一个消息队列。

每一个线程最多只可以拥有一个MessageQueue数据结构。创建一个线程的时候,并不会自动 创建其MessageQueue。通常使用一个Looper对象对该线程的MessageQueue进行管理。

3、Looper: 是MessageQueue的管理者。

每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的。创建一个Looper对象时,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,其他线程默认是没有MessageQueue对象的,所以,不能接受Message。

4、Handler: 消息的处理者

handler 负责将需要传递的信息封装成Message,通过调用handler 对象的obtainMessage()来实现;将消息传递给Looper,这是通过handler 对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。当Looper对象看到MessageQueue中含有Message,就将其广播出去。

线程间如何传递消息

这里分了四种情况:1、主线程给自己发消息;2、其他线程给主线程发消息;3、主线程给其他线程发送消息;4、其他线程发送消息。为每种情况,我写了一个小的demo实现其基本流程。

1、 主线程给自己发送消息

由于,主线程由系统自动为其创建Looper对象,并开启消息循环,所以,我们在主线程创建Handler对象时不需要显示创建Looper对象。

代码清单一:

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
msg = (TextView) findViewById(R.id.msg);
button.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
//Looper looper = Looper.getMainLooper();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
MainActivity.this.msg.setText("我是主线程的Handler,收到消息:"
+ (String) msg.obj);
}
};
Message msg = handler.obtainMessage(1, 1, 1, "主線程發消息了");
handler.sendMessage(msg);

}
});
}


2、 其他线程给主线程发送消息

其实这里还是要用到主线程的Looper创建handler,所以只要在主线程创建好handler对象然后利用构造或者其他public方法将handler对象传递给其他线程,在其他线程中用主线程的handler发送消息。

代码清单二:

其他线程代码:

package com.example.handlerdemo;
import android.os.Handler;
import android.os.Message;

public class MyThread extends Thread {
private Handler handler;

public MyThread(Handler handler) {
this.handler = handler;
}

@Override
public void run() {
Message msg = handler.obtainMessage(1, 1, 1, "其他线程发消息了");
handler.sendMessage(msg);
}
}


主activity的onCreate方法

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
msg = (TextView) findViewById(R.id.msg);
button.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
//Looper looper = Looper.getMainLooper();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
MainActivity.this.msg.setText("我是主线程的Handler,收到消息:"
+ (String) msg.obj);
}
};
new MyThread(handler).start();

}
});
}


3、主线程给其他线程发送消息

由于要在非主线程中创建handler对象,此时就需要显式启用Looper,如果直接new handler的话会报错误:E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception

E/AndroidRuntime( 6173): java.lang.RuntimeException: Can’t create handler inside thread that has not called Looper.prepare()

代码清单三:

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyThread().start();
button = (Button) findViewById(R.id.button);
textView = (TextView) findViewById(R.id.msg);
button.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
Message message = handler.obtainMessage(1, "主线程发送消息");
handler.sendMessage(message);

}
});
}
class MyThread extends Thread {
@Override
public void run() {
Looper.prepare();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i("test", "test");

}
};
Looper.loop();
}
}


4、其他线程给自己发送消息

代码清单三:

//  class MyHandler extends Handler{
//      public MyHandler(Looper looper) {
//          super(looper);
//      }
//      @Override
//      public void handleMessage(Message msg) {
//          // TODO Auto-generated method stub
//          super.handleMessage(msg);
//          textView.setText((String)msg.obj);
//      }
//  }
class MyThread extends Thread{
@Override
public void run() {
Looper.prepare();
handler = new Handler(){

@Override
public void handleMessage(Message msg) {
if (msg.what == 1 && msg.obj.equals("myself")) {
handler = new Handler(Looper.getMainLooper()){
public void handleMessage(Message msg) {
super.handleMessage(msg);
textView.setText((String)msg.obj);
};
};
//handler = new MyHandler(Looper.getMainLooper());
}
Message message = handler.obtainMessage(1, 1, 1, "告诉主线程,我收到自己发送的消息");
handler.sendMessage(message);

}
};
Message message = handler.obtainMessage(1,1,1,"myself");
handler.sendMessage(message);
Looper.loop();
}
}
}


安卓多线程应用场景

Android系统为了提高程序的实时响应能力,不允许在UI线程中进行耗时的操作,否则会出现ANR异常,因此必须将耗时的任务放到非UI线程中执行。Android/Java提供了很多类来帮助大家完成异步操作,比如:Thread类,Timer类,AsyncTask类,HandlerThread类,以及Executor接口。

1. 单项异步任务

场景:文件操作,如下载和拷贝文件

方案:Thread类,AsyncTask类

比较:Thread更适合执行一些不需要跟UI频繁交互的单项任务,而AsyncTask相反

2.定时执行的任务

场景:定时刷新UI

方案:“Thread + sleep”,定时器Timer

比较: Timer是由系统创建异步通知的定时器,会更加准确

3. 工作线程

场景:“生产者–消费者”模式,TCP Server端命令处理程序

方案: “Thread + condition/lock” ,HandlerThread类,线程池Executor

比较:前面的两种方式,都是“串行”的方式在执行“命令”,如果希望提供并发性,同时开启和管理多个线程来执行任务,则可以考虑使用Executor。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: