Handler

Handler

什么是handler

  • 简单来说,handler是一个消息处理机制,可以将消息(Message)从一个线程发送到另一个线程,并在目标线程中处理这些消息。通过handler我们可以实现线程之间的通信和更新ui。比如,在子线程中执行完网络请求后,我们可以通过handler将请求结果封装成消息发送到主线程,然后在主线程中的Handler中处理这些消息并更新UI,这样就可以避免在子线程中进行UI操作

Handler的使用

public class MainActivity extends AppCompatActivity {

    private TextView textView;
    private Handler handler;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView);
        // 创建Handler对象,并与主线程的消息队列关联
        handler = new Handler();
        // 模拟在子线程中获取数据,然后发送消息给主线程更新UI
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000); // 模拟耗时操作
                    String data = "今天天气真好";
                    // 使用Handler的post方法发送一个Runnable对象到主线程
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            // 在主线程中更新UI
                            textView.setText(data);
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        // 启动子线程
        thread.start();
    }
}

我们在onCreate()方法中创建了一个Handler对象,并将其与主线程的消息队列关联。接着,我们在子线程中模拟了一个耗时操作,并在操作完成后使用Handler的post()方法发送一个Runnable对象到主线程。在主线程的run()方法中,我们可以更新界面上的textView控件,将其文本设置为"今天天气真好"。可以看到在子线程的耗时操作完成后,通过Handler发送消息到主线程,从而实现了在主线程中更新UI的操作。

Handler的基本原理

  handler里面4个重要的角色,分别是Message,Handler,MessageQueue,Looper,

  1. Message表示消息,由它携带我们需要发送的消息,Handler接收和处理的消息对象

  2. Handler表示处理者,负责消息的发送和处理,在子线程调用sendMessage方法发送消息对象Message

  3. mesagequeus就是消息队列的意思,存放所有通过sendMessage()发送过来的消息

  4. looper 消息的管家,用于管理mesagequeus,从mesagequeus中无限循环查询是否有消息,有消息就取出来传递到Handler的handleMessage()方法中

handler的使用场景有哪些

  • 最常见的使用场景是在子线程中执行耗时操作,比如UI更新,定时任务,处理异步请求结果

handler与线程的关系是什么

  Android开发中遇到需要在不同的线程间进行通信的情况时,就需要使用Handler。它帮助我们在不同的线程传递消息。我们可以把线程看成一个人,每个人都有自己的任务。主线程就像是一个负责管理和展示UI的人,而工作线程则负责执行一些耗时的任务

  当工作线程完成任务后,想要更新主线程的UI,就需要使用Handler。我们可以在工作线程中创建一个Handler对象,然后通过这个Handler对象给主线程发送消息。这个消息里面包含了需要更新UI的一些信息

  等主线程将接收到的消息按顺序进行处理,这样就实现了工作线程与主线程之间的通信。使用Handler还可以配合其他组件来实现更复杂的功能

handler和Looper之间的关系是什么

  Handler和Looper之间是一种协作关系,Handler用于发送和处理消息,而Looper则负责消息的循环分发。

  • Looper是线程级别的消息循环器,每个线程只有一个Looper对象,它通过一个无限循环来等待处理消息队列中的消息。当Looper启动后,消息队列就会被创建,并且可以不断地向消息队列中加入消息。

  • Handler则是与Looper关联的消息处理器。一个Handler对象可以与一个特定的Looper对象进行绑定,以便接收和处理该Looper对应的消息队列中的消息。Handler可以通过sendMessage()、post()等方法将消息发送到消息队列中,并在Looper循环时被取出并处理。当Handler处理完消息后,可以执行相应的操作,例如更新UI等。

在Android中为什么需要使用handler

  在Android中使用Handler主要是为了实现异步操作和线程间通信。一般情况下Android中的UI控件只能在主线程更新,如果在子线程中直接修改UI控件会导致程序崩溃。而使用Handler可以将要更新UI控件的操作封装成一个消息,然后通过Handler发送到主线程中,由主线程中的Handler接收并处理消息,从而实现在子线程中更新UI控件的目的。

  还有程序在运行过程中还存在一些耗时的操作,例如网络请求、文件读写等等,在主线程中执行这些操作会导致界面卡顿,影响用户体验。使用Handler可以将这些耗时操作放在子线程中执行,然后通过Handler将结果发送到主线程中进行处理,从而避免阻塞主线程,提高性能。

handler如何保证线程安全

在使用Handler时,我们需要注意以下几点来保证线程安全:

  1. 在创建Handler对象时,通常会将其与特定的线程关联起来,在该线程中使用Handler进行消息处理。这样可以确保Handler的操作都在同一个线程中执行,避免多线程并发访问导致的线程安全问题。

  2. 当多个线程同时操作Handler时,需要同步机制来保证线程安全。可以使用锁synchronized关键字或其他线程安全的数据结构来控制对Handler的访问。

  3. Handler中的某些操作可能是多个步骤组成的,为了保证线程安全,可以使用volatile关键字来实现原子操作

  4.HandlerThread是一个带有Looper的线程类,它内部已经处理了Looper的创建和循环,可以直接使用该线程进行消息处理。通过HandlerThread,可以保证Handler的操作都在同一个线程中执行,避免多线程并发带来的线程安全问题。

  5.在使用Handler时,需要注意避免造成内存泄漏。常见于Handler是非静态的持有外部内的引用,发送延时消息时,Message的target是Handler的强引用,而Handler持有外部Activity的引用,由于Message在MessageQueue里,所以导致外部Activity无法被回收导致的内存泄漏

HandlerThread

   HandlerThread 是 Android 提供的一种特殊的线程类,它内部已经封装了Looper和MessageQueue,可以方便地进行消息处理。它是基于普通的Thread类实现的使用HandlerThread 的好处在于它内部已经处理了Looper 的创建和循环,我们只需要简单地获取 HandlerThread 的 Looper 并创建 Handler 对象即可。这样,我们就可以在 HandlerThread的线程中执行耗时任务,而不会阻塞主线程。

  由于 HandlerThread 是基于 Thread实现的,我们也可以像使用普通的线程一样,对它进行控制,比如暂停、恢复和停止等操作。此外,我们还可以通过 HandlerThread 的 quit() 方法来停止HandlerThread,从而终止线程。

AsyncTask

  AsyncTask可以帮助我们在后台执行一些耗时的任务,而不会阻塞主线程。我们只需要继承 AsyncTask 类,并实现其中的几个方法即可。其实AsyncTask 的核心思想就是将执行异步操作的线程与主线程分离,让主线程专注于处理用户界面的交互和更新,同时在后台线程中执行耗时操作。

IntentService

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值