欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Handler消息传递机制

程序员文章站 2022-07-14 15:12:47
...

Handler机制的由来

Android的消息传递机制是另一种形式的“事件处理”,这种机制主要是为了解决多线程问题————Android只允许UI线程修改UI组件,这会导致子线程无法修改界面组件的属性。
但实际上在开发中,经常需要在新线程周期性的改变UI组件,这时需要借助Handler的消息机制。

Handler类

主要有两个作用:

  • 在新线程中发送消息
Handler handler;
//1.有消息内容时
Message msg = new Message();
msg.what = 0x123;//消息代号
msg.obj = num.toString();//消息内容
handler.sendMessage(msg);//有消息内容时调用

//2.也可以使用Bundle传递消息内容
Bundle bundle = new Bundle();
bundle.putInt("num",123);
Message message = new Message();
message.what = 0x123;//消息代号
message.setData(bundle);
handler.sendMessage(message);

//3.无消息内容时
handler.sendEmptyMessage(0x234);//无消息内容时调用
  • 在主线程中获取,处理消息
handler = new Handler() {
   @Override
   public void handleMessage(Message msg) {
      if (msg.what == 0x123) {//1.判断是哪个个代号的消息
       msg.obj.toString();//2.获取消息传递的内容
       int num = msg.getData.getInt("num");//3.获取使用Bundle传递的内容
      //4.事物处理(可处理UI组件)
    }
 }
};

Handler,Loop与MessageQueue

  • Message:Handler接收和处理的消息对象
  • Looper:每个线程只能有一个Looper。loop方法负责读取MessageQueue中的消息,读取消息后交给发送该消息的Handler进行处理。
  • MessageQueue:消息队列,先进先出的方式管理Message。创建Looper对象时,同时创建MessageQueue对象。由Looper负责管理,即使用Handler机制处理消息时,当前线程必须有一个Looper对象。
    • UI线程:自动初始化Looper对象,直接处理即可。
    • 子线程:调用Looper.prepare()方法即可。

示例1:自动播放图片

布局界面一个ImageView即可。

public class ImageActivity extends AppCompatActivity {
    Handler handler;
    ImageView imageView;
    public static int[] imageIds = new int[]
            {
                    R.drawable.bomb5, R.drawable.bomb6, R.drawable.bomb7
                    , R.drawable.bomb8, R.drawable.bomb9, R.drawable.bomb10
                    , R.drawable.bomb11, R.drawable.bomb12, R.drawable.bomb13
                    , R.drawable.bomb14, R.drawable.bomb15, R.drawable.bomb16
            };
    int current = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_images);
        imageView = (ImageView) findViewById(R.id.img);
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == 0x234) {//接收对应消息的代码
                    imageView.setImageResource(imageIds[current++ % imageIds.length]);
                }
            }
        };
      //计时器,周期性执行指定任务
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                handler.sendEmptyMessage(0x234);//发送无内容的消息代号
            }
        }, 0, 1200);//指定播放延时

    }
}

模拟器运行以上代码,会循环每隔1.2秒改变一次图片。

示例2:模拟耗时任务改变UI组件

子线程执行耗时任务

public class PrimeNum {
    public static void primeNum(final Handler handler, final int n) {
        class myThread extends Thread {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);//增加耗时2秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                List<Integer> num = new ArrayList<>();
                //计算质数
                outer:
                for (int i = 2; i <= n; i++) {
                    for (int j = 2; j <= Math.sqrt(i); j++) {
                        if (i != 2 && i % j == 0) {
                            continue outer;
                        }
                    }
                    num.add(i);
                }

                Message msg = new Message();
                msg.what = 0x123;//消息代号
                msg.obj = num.toString();//消息内容
                handler.sendMessage(msg);//发送有内容的消息
            }
        }
        new myThread().start();
    }
}

Activity

xml一个TextView显示质数即可。

public class MainActivity extends AppCompatActivity{
    private TextView text;
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = (TextView) findViewById(R.id.text);
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == 0x123) {//接收指定代号的消息
                    text.setText(msg.obj.toString());//改变UI
                }
            }
        };
        PrimeNum.primeNum(handler, 10000);//执行耗时任务
    }

}

执行以上代码会在子线程运行2秒后,计算质数,返回将计算的结果显示在TextView。

相关标签: handler机制