• android学习笔记----HandlerThread学习


    HandlerThread源码不多,分析源码之前首先要弄懂Handler,MessageQueue与Looper关系

    android学习笔记----Handler的使用、内存泄漏、源码分析等一系列问题

    关于HandlerThread源码分析可以见这里:

    https://blog.csdn.net/lmj623565791/article/details/47079737

    直接上笔记,来讲解一下上面博客的代码中的疑惑点:

    import android.os.Bundle;
    import android.os.Handler;
    import android.os.HandlerThread;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.text.Html;
    import android.util.Log;
    import android.widget.TextView;
    
    
    public class HandlerThreadActivity extends AppCompatActivity {
        private TextView mTvServiceInfo;
        private static final String TAG = "HandlerThreadActivity";
        private HandlerThread mCheckMsgThread;
        private Handler mCheckMsgHandler;
        private boolean isUpdateInfo;
        private static final int MSG_UPDATE_INFO = 0x110;
        //与UI线程管理的handler
        private Handler mHandler = new Handler();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_thread_handler);
            //创建后台线程
            initBackThread();
            mTvServiceInfo = (TextView) findViewById(R.id.id_textview);
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            //开始查询
            isUpdateInfo = true;
            mCheckMsgHandler.sendEmptyMessage(MSG_UPDATE_INFO);
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            //停止查询
            isUpdateInfo = false;
            mCheckMsgHandler.removeMessages(MSG_UPDATE_INFO);
        }
    
        private void initBackThread() {
            mCheckMsgThread = new HandlerThread("check-message-coming");
            mCheckMsgThread.start();
            mCheckMsgHandler = new Handler(mCheckMsgThread.getLooper()) {
                // 执行回调的handlerMessage方法,看Looper在哪个线程,就在哪个线程执行
                // 所以mCheckMsgHandler代表子线程的Handler
                @Override
                public void handleMessage(Message msg) {
                    checkForUpdate();
                    if (isUpdateInfo) { // 必须要此标志为才能及时停止消息
                        Log.d(TAG, "=======handleMessage: " + Thread.currentThread().getName());
                        mCheckMsgHandler.sendEmptyMessageDelayed(MSG_UPDATE_INFO, 1000);
                    }
                }
            };
        }
    
        /**
         * 模拟从服务器解析数据
         */
        private void checkForUpdate() {
            try {
                //模拟耗时
                Thread.sleep(1000);
                // 执行post方法看Handler对象绑定的哪个Looper,Looper属于哪个线程,这个Runnable对象就在哪个线程执行
                // 所以mHandler代表主线程的Handler
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Log.d(TAG, "==========run: " + Thread.currentThread().getName());
                        String result = "实时更新中,当前大盘指数:<font color='red'>%d</font>";
                        result = String.format(result, (int) (Math.random() * 3000 + 1000));
                        mTvServiceInfo.setText(Html.fromHtml(result));
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            //释放资源
            mCheckMsgThread.quit();
        }
    }

    打印log,部分运行结果

    ......

    批注: 执行回调的handlerMessage方法,看Looper在哪个线程,handler就属于哪个线程,就在哪个线程执行。执行post方法也看Handler对象绑定的哪个Looper,Looper属于哪个线程,handler属于对应线程,这个Runnable对象就在哪个线程执行,这里mHandler在主线程实例化,绑定了主线程的Looper,所以mHandler属于主线程,这个Runnable的run()方法就在main线程执行。

    在这里mCheckMsgHandler = new Handler(mCheckMsgThread.getLooper()){...}这个mCheckMsgThread是HandlerThread对象,所以getLooper出来的Looper对象是属于子线程的,所以mCheckMsgHandler是子线程的Handler对象,这个回调的handlerMessage方法是在子线程check-message-coming执行的。而调用post方法的Handler对象mHandler是在主线程实例化的,mHandler绑定了主线程的Looper,所以这个Runnable的run()方法就在main线程执行。这里不是start()开启新线程执行,而是直接执行run()方法,上一篇android学习笔记----Handler的使用、内存泄漏、源码分析等一系列问题已经解释过这个问题,源码写了的。

    我们定义了标志位private boolean isUpdateInfo;是为了及时stop消息采用的,如果不要这个标志位,哪怕锁屏后执行的onPause()中mCheckMsgHandler.removeMessages(MSG_UPDATE_INFO);但是可能此时正好回调handleMessage,消息队列此时没有消息了,remove不了,此时已经锁屏,但handleMessage中又继续发送消息,不断循环了。

    布局文件

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <TextView
            android:id="@+id/id_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="正在加载大盘指数..." />
    
    </RelativeLayout>

    ========================Talk is cheap, show me the code=======================

    CSDN博客地址:https://blog.csdn.net/qq_34115899
  • 相关阅读:
    linux 解压文件
    linux 文件夹操作
    adb 安装apk报INSTALL_FAILED_NO_MATCHING_ABIS
    Android Tab类型主界面 Fragment+TabPageIndicator+ViewPager
    Android 图表
    Android Manifest文件
    BroadcastReceiver介绍
    Android dimen
    Android Dialog
    Android 获取加速传感器的值,并去除杂音
  • 原文地址:https://www.cnblogs.com/lcy0515/p/10807836.html
Copyright © 2020-2023  润新知