当前位置: 代码迷 >> Android >> 玩转Android-组件篇-Handler的运用(2)
  详细解决方案

玩转Android-组件篇-Handler的运用(2)

热度:73   发布时间:2016-05-01 17:07:14.0
玩转Android---组件篇---Handler的使用(2)

对于Handler来说,它和与它调用它的Activity是出于同一线程的,上一篇并没有调用线程
的start方法,而是直接执行的run方法。而启动一个线程是调用的start方法

上一篇博客里的对Handler的调用时通过Runnable接口来实现的,并且是通过run()方法来启动那个线程的,而且是Activity和Handler是两个线程独立运行的,互补干扰,但是实际情况确实,Activity所在的线程和Handler的线程是同一个线程,下面进行一下实验

?

package org.hualang.handlertest3;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.util.Log;public class HandlerTest3 extends Activity {    private Handler handler = new Handler();    private String TAG = "System.out";    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        handler.post(r);        setContentView(R.layout.main);        //Thread t = new Thread(r);        //t.start();                Log.d(TAG,"Activity id:"+Thread.currentThread().getId());        Log.d(TAG,"Activity name:"+Thread.currentThread().getName());            }    Runnable r = new Runnable()    {    	public void run()    	{    		Log.d(TAG,"Handler id:"+Thread.currentThread().getId());            Log.d(TAG,"Handler name:"+Thread.currentThread().getName());            try {				Thread.sleep(5000);			} catch (InterruptedException e) {				// TODO Auto-generated catch block				e.printStackTrace();			}    	}    };}

?

运行结果:

证明是同一个线程的两个依据:

①Activity的id或name和Handler的id或name是同样的

②我设置了

?handler.post(r);
?setContentView(R.layout.main);

也就是,如果执行后马上显示文本信息,那么可以证明它们不在同一个线程,但是实际情况是要先执行了handler后5秒,才显示文本信息,说明它们在同一线程



?

?

如果将代码改为

        //handler.post(r);        setContentView(R.layout.main);        Thread t = new Thread(r);        t.start();

?再次执行,运行结果如下,通过start启动线程,它们不在同一个线程中

?

?

----------------------------------------

Looper即循环的从队列当中取得消息的功能,如果在线程中使用Looper
那么,就会循环的从线程队列当中取得消息并处理,如果队列当中没有消息的话
,线程就进入了休眠状态

Looper很少自己创建,在Android中给出了HandlerThread类,并且具有循环取得并处理消息的功能

?

下面来实现这种Activity和Handler分别在两个线程中执行,实现真正的异步处理

package org.hualang.handlertest;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.HandlerThread;import android.os.Looper;import android.os.Message;import android.util.Log;public class HandlerTest4 extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        Log.d("System.out","Activity所在线程的id:"+Thread.currentThread().getId());        /**         * 生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能         * 这个类由Android应用程序框架提供         */        HandlerThread handlerThread = new HandlerThread("handlerThread");        handlerThread.start();        MyHandler handler = new MyHandler(handlerThread.getLooper());        Message msg = handler.obtainMessage();        /**         * 将Message对象发送到目标对象         * 所谓的目标对象,就是生成该msg对象的handler对象         */        msg.sendToTarget();    }    class MyHandler extends Handler    {    	public MyHandler()    	{	    	}    	public MyHandler(Looper looper)    	{    		super(looper);    	}    	public void handleMessage(Message msg)    	{    		Log.d("System.out", "handler所在线程的id:"+Thread.currentThread().getId());    	}    }}

?

运行结果:



?

可以看到,Activity和Handler是在两个不同的线程中执行的,这样就是实现了真正的异步处理

1、首先创建一个HandlerThread对象,这个HandlerThread类实现了循环的取得消息并处理

2、用start方法启动一个新线程

3、创建MyHandler类,里面传递的参数即Looper方法所获得的可以循环在队列中取得的消息

4、MyHandler类调用的是带参数Looper的构造方法,并且实现了handlerMessage方法

5、获取一个Message对象

6、将这个对象发送到生成该msg对象的handler对象,从而执行了handleMessage方法

?

-----------------------------------------------------------------

最后,将说一下Message里传送的数据的使用,这里的msg对象可以使用arg1,arg2或者obj

arg1 and arg2 are lower-cost alternatives to using setData() if you only need to store a few integer values. 也就是相对于setData()方法,如果你仅仅保存一些简单的整形数的话,arg1,arg2对资源的要求较低,而setData()方法一般用于传递大量数据的时候会用到

?

如果是msg.obj,那么可以这样用

msg.obj = "Welcome to china";

然后在handleMessage()方法中用

String str = (String)msg.obj;来获得传递的值

?

如果使用getData()方法的话,需要用到Bundle对象来传递,下面用个例子来说明

        Bundle b = new Bundle();        b.putInt("age", 22);        b.putString("name", "loulijun");        msg.setData(b);        msg.sendToTarget();

?

上面的代码用来设置要传递的数据

下面的代码用来获取Bundle传递过来的数据并且用Toast来显示

Bundle b = msg.getData();    		int age = b.getInt("age");    		String name = b.getString("name");    		Toast toast = Toast.makeText(getApplicationContext(), "age="+age+"name="+name, Toast.LENGTH_LONG);    		toast.show();

?

package org.hualang.handlertest;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

public class HandlerTest4 extends Activity {
??? /** Called when the activity is first created. */
??? @Override
??? public void onCreate(Bundle savedInstanceState) {
??????? super.onCreate(savedInstanceState);
??????? setContentView(R.layout.main);
??????? Log.d("System.out","Activity所在线程的id:"+Thread.currentThread().getId());
??????? /**
???????? * 生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能
???????? * 这个类由Android应用程序框架提供
???????? */
??????? HandlerThread handlerThread = new HandlerThread("handlerThread");
??????? /**
???????? * 使用HandlerThread的getLooper()方法之前,必须先调用该类的start()方法,否则是个null,会报错
???????? */
??????? handlerThread.start();
??????? MyHandler handler = new MyHandler(handlerThread.getLooper());
??????? Message msg = handler.obtainMessage();
??????? /**
???????? * 将Message对象发送到目标对象
???????? * 所谓的目标对象,就是生成该msg对象的handler对象
???????? */
??????? //msg.obj = "Hello world";
??????? Bundle b = new Bundle();
??????? b.putInt("age", 22);
??????? b.putString("name", "loulijun");
??????? msg.setData(b);
??????? msg.sendToTarget();
??? }
??? class MyHandler extends Handler
??? {
??? public MyHandler()
??? {
??? }
??? public MyHandler(Looper looper)
??? {
??? super(looper);
??? }
??? public void handleMessage(Message msg)
??? {
??? //String str = (String)msg.obj
??? Bundle b = msg.getData();
??? int age = b.getInt("age");
??? String name = b.getString("name");
??? Toast toast = Toast.makeText(getApplicationContext(), "age="+age+"name="+name, Toast.LENGTH_LONG);
??? toast.show();
??? Log.d("System.out", "handler所在线程的id:"+Thread.currentThread().getId());
??? }
??? }
}

?运行结果:



?

?

1 楼 q6684273 2011-06-02  
以前是搞EE的,现在搞 Andorid 了,lz写的不错,学习了。
2 楼 294460620 2011-06-22  
写得很不错,学习中,
3 楼 让安卓飞一会 2011-06-28  
火星哥视频里的东西~~讲得木有马士兵好~~
  相关解决方案