消息队列处理模型
容器保存事件,队列
涉及到角色:
类 功能
MessageQueue 存放消息
Looper 轮循消息队列,从中取出消息
Thread 处理消息
Message 消息
Handler 在其他线程发消息给当前线程
1.looper的例子及说明
由Looper决定
Looper对象在哪个线程创建,
Handler的handleMessage方法就在哪个线程执行
public class MainActivity extends Activity { private Handler mHandler; int what = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.button1).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mHandler.sendEmptyMessage(what ++);//主线程发送 new Thread("aaa") { public void run() { mHandler.sendEmptyMessage(what ++);//“aaa”子线程发送 } }.start(); } }); new Thread("自定义消息队列") {//单线程处理所有线程发过来的消息,会以队列的顺序排队执行 public void run() { Looper.prepare(); //查看prepare()里80行和189行,创建了messageQueue、looper mHandler = new Handler(Looper.myLooper()) //Looper.myLooper()得到当前线程的looper { //handler在哪个线程处理消息,取决于Looper在哪个线程创建 @Override public void handleMessage(Message msg) { String content = "当前线程:" + Thread.currentThread().getName() + "msg:" + msg.what; Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show(); } }; Looper.loop();//looper开始轮循队列 } }.start(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
注意:
在子线程中直接new handle()会出现以下错误,是因为子线程中默认没有创建Looper对象,需要先调用Looper.prepare()方法启用Looper。主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环。
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()
2. HandlerThread
封装了Thread和Looper、MessageQueue
public class MainActivity extends Activity { private Handler mHandler; int what = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.button1).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mHandler.sendEmptyMessage(what ++);//主线程发送 new Thread("aaa") { public void run() { mHandler.sendEmptyMessage(what ++);//“aaa”子线程发送 } }.start(); } }); // 因为HandlerThread()里面已经封装好了Looper.prepare()和Looper.loop(); HandlerThread thread = new HandlerThread("自定义消息队列"); thread.start(); //thread.getLooper()如果换成Looper.myLooper()就是得到主线程的looper mHandler = new Handler(thread.getLooper()) { //handler在哪个线程处理消息,取决于Looper在哪个线程创建 @Override public void handleMessage(Message msg) { String content = "当前线程:" + Thread.currentThread().getName() + "msg:" + msg.what; Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show(); } }; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
3. IntentService
Thread、Looper、MessageQueue、Handler、Message
MainActivity中显式意图启动service
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.button1).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) {//启动MyService,传值过去 Intent service = new Intent(MainActivity.this,MyService.class); service.putExtra("msg", "aaa"); startService(service ); } }); } }
MyService继承了IntentService,接收到MainActivity传来的值
public class MyService extends IntentService { //封装好了handleMessage();64行 // 写好了HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); // thread.start(); public MyService() {//IntentService有个有参的构造方法75行 super("消息队列IntentService"); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override protected void onHandleIntent(Intent intent) { String extra = intent.getStringExtra("msg"); String content = "当前线程:" + Thread.currentThread().getName() + "msg:" + extra; Log.e("onHandleIntent", content); } }