Android中的Thread、Looper、Handler之间的关系

其实非常简单,只要搞清楚Thread、Looper、Handler它们各自的作用就OK了。


  • Thread 这个大家都知道就是线程,线程中包括一个消息队列(Message Queue),一个循环处理消息队列中消息的工具(Looper)。
  • Looper 这个可能有点陌生,就是Thread中的一个用来开启消息循环的工具,循环的取出Message Queue中的消息来让Thread执行。
  • Handler 这个可以看作是Looper的一个接口,具体怎么处理消息是在Handler中定义的(handleMessage()方法中定义)。

知道三者的含义那么就好说,剩下的就是怎么把它们给联系起来,由于Message Queue和Looper都是Thread自带的那么就不需要new出来,主要是Looper有点特殊,就是在使用Looper前必需 调用Looper.prepare()来初始化Thread的Looper,然后调用Looper.loop()来让Looper循环处理Message Queue中的消息(写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行)。但是怎么向Message Queue中发送消息以及如何处理消息就需要我们自定义了,这就用到了 Handler ,Handler是与Looper绑定的。在调用了Looper.prepare()后,将Handler与Looper绑定就OK了。怎么绑定看下面:


首先明确一下,在android主线程(UI线程)也是一个线程,它里面也有Message Queue、Looper,只是android自动给主线程将Looper设置好了,那么要给主线程通讯我们只需要在主线程 new一个handler:

Handler mHandler = new Handler()//将主线程的Looper与handler绑定;
并且实现它里面的 handleMessage()方法即可(将消息发送给主线程)。
在这里没有看到Looper与Handler的绑定,其实在这个无参构造函数中 有这么句代码:
mLooper = Looper.myLooper();

无参构造函数直接取 当前所在线程的Looper,如果在子线程中没有执行Looper.prepare()方法就调用会报错,因为如果不执行Looper.prepare()方法,Looper还没有初始化。

下面看一个例子就全OK了(是两个子线程之间通信):

public class ServiceTestThreadCommunication extends Service {

	private static final String TAG = "ServiceTestThreadCommunication";

	Looper mLooper;
	ServiceHandler mHandler;
	
	boolean isThread1Ready = false;
	
	Object mLock = new Object();

	@SuppressLint("HandlerLeak")
	private final class ServiceHandler extends Handler {
		
		public ServiceHandler(Looper looper){
			super(looper);
		}

		@Override
		public void handleMessage(Message msg) {

			Log.d(TAG, "当前线程 ==" + Thread.currentThread().getName()
					+ "== 接收到来自 ==" + msg.obj.toString() + "== 线程的信息");

			ServiceTestThreadCommunication.this.stopSelf();
			super.handleMessage(msg);
		}
	}
	
	
	

	@Override
	public void onCreate() {
		super.onCreate();
		
		
		ServiceThread1 thread1 = new ServiceThread1("thread1");
		ServiceThread2 thread2 = new ServiceThread2("thread2");
		
		thread2.start();
		thread1.start();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {


		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO: Return the communication channel to the service.
		throw new UnsupportedOperationException("Not yet implemented");
	}
	
	
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		if(null != mLooper){
			mLooper.quit();
		}
	}



	private class ServiceThread1 extends Thread{

		public ServiceThread1(String string) {
			super(string);
			isThread1Ready = false;
		}

		@Override
		public void run() {

			synchronized(mLock){
				Looper.prepare();
				mLooper = Looper.myLooper();
				mHandler = new ServiceHandler(mLooper);
				isThread1Ready = true;
				mLock.notifyAll();
			}
			Looper.loop();
		}
		
	}
	
	private class ServiceThread2 extends Thread{
		public ServiceThread2(String string) {
			super(string);
		}

		@Override
		public void run() {
			while(!isThread1Ready){
				synchronized(mLock){
					try {
						mLock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
			Message msg = Message.obtain();
			msg.obj = getName();
			mHandler.sendMessage(msg);
		}
	}
}


下面再看一个google的例子,是主线程与子线程通信的例子:

public class HelloService extends Service {
  private Looper mServiceLooper;
  private ServiceHandler mServiceHandler;

  // Handler that receives messages from the thread
  private final class ServiceHandler extends Handler {
      public ServiceHandler(Looper looper) {
          super(looper);
      }
      @Override
      public void handleMessage(Message msg) {
          // Normally we would do some work here, like download a file.
          // For our sample, we just sleep for 5 seconds.
          long endTime = System.currentTimeMillis() + 5*1000;
          while (System.currentTimeMillis() < endTime) {
              synchronized (this) {
                  try {
                      wait(endTime - System.currentTimeMillis());
                  } catch (Exception e) {
                  }
              }
          }
          // Stop the service using the startId, so that we don't stop
          // the service in the middle of handling another job
          stopSelf(msg.arg1);
      }
  }

  @Override
  public void onCreate() {
    // Start up the thread running the service.  Note that we create a
    // separate thread because the service normally runs in the process's
    // main thread, which we don't want to block.  We also make it
    // background priority so CPU-intensive work will not disrupt our UI.
    HandlerThread thread = new HandlerThread("ServiceStartArguments",
            Process.THREAD_PRIORITY_BACKGROUND);
    thread.start();

    // Get the HandlerThread's Looper and use it for our Handler
    mServiceLooper = thread.getLooper();
    //在这里Handler是在UI线程中new出来的,但是它与HandlerTread的Looper绑定了,所以
    //ServiceHandler中的handleMessage()方法是在HandlerThread这个线程中执行的。
    mServiceHandler = new ServiceHandler(mServiceLooper);
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

      // For each start request, send a message to start a job and deliver the
      // start ID so we know which request we're stopping when we finish the job
      Message msg = mServiceHandler.obtainMessage();
      msg.arg1 = startId;
      mServiceHandler.sendMessage(msg);

      // If we get killed, after returning from here, restart
      return START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
      // We don't provide binding, so return null
      return null;
  }

  @Override
  public void onDestroy() {
    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
  }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
In Android, Looper and Handler work together to execute tasks on a separate thread, also known as a background thread. A Looper is an object that allows a thread to handle incoming messages or tasks. It runs in an infinite loop, waiting for new tasks to arrive. When a new task arrives, the Looper dispatches it to the appropriate Handler for processing. A Handler is an object that receives tasks from the Looper and processes them. It is associated with a specific thread, and when a task is sent to a Handler, it is added to a message queue. The Handler processes the tasks one by one, in the order they were added to the queue. Together, the Looper and Handler allow us to perform time-consuming tasks on a separate thread, without blocking the main thread. The main thread is responsible for handling UI events, and if it is blocked by a long-running task, the user interface will become unresponsive. By using Looper and Handler, we can keep the main thread free to handle UI events while executing time-consuming tasks on a separate thread. Here is an example of how Looper and Handler work together: ``` public class MyThread extends Thread { public Handler handler; @Override public void run() { Looper.prepare(); handler = new Handler() { @Override public void handleMessage(Message msg) { // Process the task here } }; Looper.loop(); } } ``` In this example, we create a new thread called `MyThread`. In the `run()` method, we create a new `Looper` and call `prepare()` to initialize it. We then create a new `Handler` and associate it with the thread. Finally, we call `Looper.loop()` to start the infinite loop and wait for tasks to arrive. To send a task to `MyThread`, we can use the `handler` object: ``` MyThread myThread = new MyThread(); myThread.start(); Message msg = myThread.handler.obtainMessage(); msg.obj = "Hello"; myThread.handler.sendMessage(msg); ``` In this example, we create a new message and set its `obj` property to `"Hello"`. We then send the message to `MyThread` using its `handler` object. When the message arrives, the `handleMessage()` method of the `Handler` will be called, and we can process the task there.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值