【达内课程】线程中Handler与Looper

news/2024/7/7 5:43:35 标签: looper, handler

文章目录

  • 概念介绍

概念介绍

【消息机制中的角色】
Message:消息的载体,用于封装消息的相关数据
Handler:消息的发送者与处理者,用于发送消息,并处理消息
MessageQueue:(在编程时不会使用到)消息队列,若干个消息的容器
Looper:轮询者,从消息队列中获取数据,并交给运行在主线程的 Handler 进行处理

xml
xml中增加一个按钮来发送消息

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_send_msg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发出消息" />

</LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btnSendMsg;
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnSendMsg = findViewById(R.id.btn_send_msg);
        btnSendMsg.setOnClickListener(this);
        handler = new Handler(new InnerHandlerCallback());
    }

    @Override
    public void onClick(View view) {
        //发出消息
        Message msg = Message.obtain(handler);
        msg.sendToTarget();
        Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " MainActivity onclick()->send message");
    }

    private class InnerHandlerCallback implements Handler.Callback {

        @Override
        public boolean handleMessage(Message message) {
            Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " InnerHandlerCallback handleMessage()->handle message");
            return false;
        }
    }
}

运行程序,查看日志,从日志可以看出 Handler 是运行在主线程的
在这里插入图片描述
现在修改 onClick 中代码,把发送消息放在子线程中

@Override
    public void onClick(View view) {
        new Thread() {
            @Override
            public void run() {
                //发出消息
                Message msg = Message.obtain(handler);
                msg.sendToTarget();
                Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " MainActivity onclick()->send message");
            }
        }.start();
    }

运行程序,查看日志,可以看到发消息在子线程,处理消息还是在主线程
在这里插入图片描述
如果把创建 Handler 也放在子线程中

@Override
    protected void onCreate(Bundle savedInstanceState) {
        ......
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                handler = new Handler(new InnerHandlerCallback());
                Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " MainActivity onCreate()->sub thread->new Handler");
                Looper.loop();
            }
        }.start();
    }

运行程序,观察日志,会发现 handle message 是同一个线程:
在这里插入图片描述
【Handler与Looper】
Handler 运行在哪个线程(在哪个线程上处理消息),取决于创建 Handler 时,关联到哪个线程上的 Looper,如果没有显示指定 Looper,则关联到当前线程

【小结】
1、在主线程创建的 Handler 对象,是运行在主线程的,所以可以直接更新 UI
2、在子线程中创建 Handler 之前,必须调用 Looper.prepare()以初始化运行在子线程中的 Looper
3、在子线程中的 Looper 必须显式的调用 Looper.loop()方法,才会开始轮询消息队列
4、在主线程中,默认就已经存在处于轮循工作状态的 Looper,而子线程中没有
5、如果没有可用的 Looper,则无法创建 Handler
6、创建 Handler 时,会默认关联当前线程上的 Looper

MessageQueue 是消息队列的意思,它主要用于存放所有通过 Handler 发送的消息。 这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个 MessageQueue 对象

Looper 是每个线程中的 MessageQueue 的管家,调用 Looper 的 loop()方法后,就会进入到一个无限循环当中,然后每当发现 MessageQueue 中存在一条消息,就会将它取出,并传递到 Handler 的 handleMessage()方法中。每个线程中也只会有一个 Looper 对象


http://www.niftyadmin.cn/n/1817663.html

相关文章

【达内课程】线程中的AsyncTask

文章目录AsyncTask介绍用AsyncTask做一个进度条的栗子取消AsyncTaskAsyncTask介绍 【同步和异步】 同步&#xff1a;就是在发出一个功能调用时&#xff0c;在没有得到结果之前&#xff0c;该调用就不返回。也就是必须一件一件事做&#xff0c;等前一件做完了才能做下一件事。 …

给大家拓宽点边界,15分钟带你入门sklearn与机器学习——分类算法篇

我经常和大家提过&#xff0c;不要给自己设限&#xff0c;这不仅包括技术设限&#xff0c;还有领域设限。那今天我就给大家分享一些关于机器学习的东西&#xff0c;不用你弄懂原理&#xff0c;记住那些专业名词&#xff0c;起码知道怎么回事&#xff0c;别人说的时候你也算半个…

【达内课程】如何理解Context上下文对象

文章目录介绍Context 数量如何获取Context引起的内存泄露正确使用Context介绍 Android 应用都是使用 Java 语言来编写的&#xff0c;思考一下&#xff0c;一个 Android 程序和一个 Java 程序&#xff0c;他们最大的区别在哪里&#xff1f;其实简单点分析&#xff0c;Android 程…

全网首份Python打包工具Pyinstaller实战指南,如丝滑般体验

写了个吊炸天的Python项目&#xff0c;把我和左手相处的时间都赔上了。但出于版权考虑&#xff0c;我不太想让使用方直接用我的代码&#xff0c;毕竟Python代码给出去&#xff0c;就真的收不回来了。 想给客户演示的时候&#xff0c;不想那么墨迹的打开dos cmd 或者 terminal …

【达内课程】图库应用(3)

文章目录开发步骤实现点击列表展示大图增加手势滑动开发步骤 1、创建 DisplayImageActivity&#xff0c;用于显示图片详情 2、在 MainActivity 中为 GridView 配置 AdapterView.OnItemClickListener 监听&#xff0c;并且在实现时&#xff0c;根据点击的 position 跳转到 Disp…

【达内课程】手势滑动

文章目录方法一&#xff1a;OnTouchListener方法二&#xff1a;构建手势探测器。OnGestureListenerOnDoubleTapListenerSimpleOnGestureListener类应用&#xff1a;识别向左滑还是向右滑在Android应用中&#xff0c;经常需要手势滑动操作&#xff0c;比如上下滑动&#xff0c;或…

5分钟了解 Python 中的super函数是如何实现继承的

Py 2.x 和 Py 3.x 中有一个很大的区别就是类&#xff0c;无论是类的定义还是类的继承。Py 3.x 中类的继承可以直接使用 super() 关键字代替原来的 super(Class, self)。 那么 super() 到底是依据什么来继承的呢&#xff1f;今天就来分析下。 super()函数根据传进去的两个参数…

添加依赖出现 Unable to resolve dependency for:xxx的报错

File-Settings 找到Gradle&#xff0c;去掉Offline work前边的对号