android的looper、handler的使用

处理线程中消息队列的方法目前我知道的分为种两种。一种是线程本身带有消息队列,如主线程和handlerThread,主线程不说了。handlerThread继承自thread但它与一般thread不同的地方是它有自己的消息队列。而一般线程(指自己创建的线程)在默认情况下没有和它相关的消息队列。要想使其有在运行消息队列的线程中调用Looper.prepare();方法。然后调用Looper.loop();去让消息队列中的消息挨个执行。如下所示:

class LooperThread extends Thread {
      public Handler mHandler;

      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }

        因为线程默认情况下是没有自己的消息队列的,所以如果在该线程的run()方法中新建handler后调用handler.post(runnable);程序会报错。但在run方法外调用就没事。因为thread类只是管理子线程的,其真正的子线程是在run方法中的。


自己写的例子如下:

package com.example.handlerdemo;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.R.integer;
import android.app.Activity;
import android.view.Menu;
import android.view.TextureView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
	Handler handler;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Button start=(Button) findViewById(R.id.button1);
		TextView textView=(TextView) findViewById(R.id.textView1);
		start.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
			
				Thread thread=new Thread(){

					@Override
					public void run() {
						// TODO Auto-generated method stub
						Looper.prepare();
						handler=new Handler(){
							@Override
							public void handleMessage(Message msg) {
								// TODO Auto-generated method stub
								super.handleMessage(msg);
								switch (msg.what) {
								case 1:
									System.out.println("thread name is"+" "+Thread.currentThread().getName());
									break;
								}
							}
						};
						handler.post(runnable);
						Looper.loop();
					}
				};
				thread.start();
			}
		});
		
	}
		Runnable runnable=new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("这是runnable1");
				handler.sendMessage(handler.obtainMessage(1));
			}
		};
		
	
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		System.out.println("looper绑定的线程是"+Looper.myLooper().getThread().getName());
		Looper.myLooper().quit();
		super.onDestroy();
		
	}
	
	}
	


其中onDestroy方法中结束looper有错误。其得到的是主线程的名字。会报错。疑问:在哪里结束Looper。有待研究。欢迎留言赐教。

handleMessage中打印出来的线程的名字是自己定义出来的线程的名字。而非主线程。而onDestroy方法中打印出来的是主线程的名字。且该处错误,不该在此处停止looper,此处疑问。

接近一年后再次回来看自己曾经的疑问,感觉那时自己好傻啊,这么明显的问题都没看出来。哎,看来自己还是进步了。窃喜。在onDestroy方法中停止的当然必须是当初的那个looper,而上文在onDestroy中quit的,是重新获得的当前线程(main)线程的looper,当然不是原来的,所以会报错啊。须将自己声明的线程中的Looper mLooper=Looper.myLooper();然后在onDestroy中直接mLooper.quit();就OK了。至于具体深入研究还需去看源码,加油吧,路上的孩子。

其中handler的还可以这样生成:

handler=new Handler(new Handler.Callback() {

@Override
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
switch (msg.what) {
case 1:
System.out.println("thread name is"+" "+Thread.currentThread().getName());
break;
}
return true;
}
});

Callback接口是Handler的内部接口。用来实例化handler避免自己生成handler子类的麻烦。

需要注意的几点

1.Looper.prepare();和Looper.loop();都是在run方法中执行。

2.handler.post(runnable);必须写在Looper.loop();方法前面,否则没有效果。

3.在runnable中可以多次调用handler.sendMessage(handler.obtainMessage(1));只是Message.what值不同就可以发送不同的消息。在handleMessage中handler就可以根据what值对不同的消息分别处理。

4.不要忘记了调用thread.start();方法。

下面说说handlerThread,其本身带有消息队列所以就不要像一般线程那样调用Looper.prepare等方法了。下面是例子代码:

package com.example.handlerdemo2;

import android.R.integer;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;

public class MainActivity extends Activity {

	private ProgressBar progressBar;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Button button=(Button) findViewById(R.id.button1);
		button.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//参数为线程的名字可通过getName返回。
				HandlerThread handlerThread=new HandlerThread("handlerthread");
				handlerThread.start();
				Handler handler=new Handler(handlerThread.getLooper(),new Handler.Callback() {
					
					@Override
					public boolean handleMessage(Message msg) {
						// TODO Auto-generated method stub
						try {
							//通过让线程休眠16秒没有报错,可以验证该是一个独立于主线程的线程。可以在此处理耗时操作。
							Thread.sleep(16000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						switch (msg.what) {
						case 1:
							System.out.println("这是message1发来的消息");
							//此处得到的名字就是初始化handlerThread时里面的参数
							System.out.println("thread name is---->"+Thread.currentThread().getName());
							break;

						case 2:
							System.out.println("这是message2发来的消息");
							System.out.println("thread name is---->"+Thread.currentThread().getName());
							break;
						}
							
						
						return true;
					}
				});
				//可以通过hanler得到不同的Message从而在handleMessage方法中对消息进行分别处理。
				Message message1=handler.obtainMessage(1);
				Message message2=handler.obtainMessage(2);
				message2.sendToTarget();
				message1.sendToTarget();
				
			}
		});
		
	}

}

其就将对Looper的处理交由handlerThread处理了自己就不用管了,方便了一些。该方法中handler的声明使该handler绑定到handlerthread的looper所在的消息队列中去了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中的Looper类主要用于管理消息循环和消息队列。在Android中,每个线程都有一个Looper对象,它用于循环处理消息队列中的消息,以便在主线程或后台线程中处理异步任务。 使用Looper类,我们可以在Android应用程序中创建一个消息循环,并将消息动态地排队到消息队列中。然后,我们可以在消息队列中处理这些消息,以便在正确的时间和正确的上下文中执行相应的操作。 以下是使用Looper类的基本步骤: 1. 创建一个Handler对象并将其附加到当前线程的Looper。 2. 在需要发送消息的地方,使用Handler的post方法将消息发送到消息队列中。 3. 在Looper所在的线程中处理消息队列中的消息。 例如,下面的代码演示了如何在后台线程中使用Looper类: ``` public class MyThread extends Thread { public Handler mHandler; @Override public void run() { Looper.prepare(); mHandler = new Handler() { @Override public void handleMessage(Message msg) { // 在此处处理消息 } }; Looper.loop(); } } ``` 在这个例子中,我们创建了一个MyThread类,并在它的run方法中创建了一个消息循环和消息队列。然后,我们创建了一个Handler对象,并将其附加到当前线程的Looper中。最后,我们调用Looper的loop方法来开始处理消息队列中的消息。 使用这种方式,我们就可以在后台线程中动态地排队和处理消息,以便在正确的时间和正确的上下文中执行相应的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值