android handlerThread 的使用
阅读原文时间:2021年04月20日阅读:1

HandlerThread 是什么?是一个Thread的子类,里面创建了一个Looper对象,并且调用Looper.loop();方法。

这个类通常用于创建子线程的handler,让其他线程通过handler#sendMessage()或者handler#postXXX()的方式,发送消息给HandlerThread,让这个线程去处理消息,执行操作,比如,访问网络等。

HandlerThread的使用以及原理 这篇写的比较清楚了。

可以看一下简单案例:

    private Looper looper;
    private Handler mHandler;

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

        HandlerThread handlerThread = new HandlerThread("sub-thread-create-by-cat");
        handlerThread.start(); // 1. 启动一个 handlerThread 线程
        looper = handlerThread.getLooper(); // 2. 获取该线程的 looper 对象
        mHandler = new H(looper); // 3. 创建一个拥有该 looper 的 handler 对象
        findViewById(R.id.btn_next)
                .setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        LogUtils.w("next...");
//                        requestArticles();
                        mHandler.sendEmptyMessage(123);
//                        startActivity(new Intent(getActivity(), RoundActivity.class));
                    }
                });
     }

     protected class H extends Handler {
        H(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            // 4. 接收消息,执行逻辑
            super.handleMessage(msg); // 可以处理耗时操作
            // 也可以更新 Ui, 比如 toast ,windowManager
            // todo: 但是不能更新当前 activity的 布局文件,因为只有创建view 的线程,才能操作 view ,具体 crush log 不记得了。

            LogUtils.w(new Date() + " ### start---" + Thread.currentThread().getName());
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(HttpRequest.BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    // 针对rxjava2.x
//                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();
            WanService service = retrofit.create(WanService.class);
            Call<BannerBean> call = service.getBannerCall();
            try {
                 // 同步的网络请求
                Response<BannerBean> execute = call.execute();
                LogUtils.w("io--->" + execute.body());
                // toast ok
                Toast.makeText(getApplicationContext(), "io->" + execute.body(), Toast.LENGTH_SHORT).show();
                LogUtils.w(execute);
//            tabView.setBackgroundColor(Color.RED); // crush
                TextView tv = new TextView(getActivity());
                tv.setBackgroundColor(Color.RED);
                tv.setText("io->" + execute.body());
                WindowManager wm = getWindowManager();
                WindowManager.LayoutParams params = new WindowManager
                        .LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
                        WindowManager.LayoutParams.WRAP_CONTENT);
                params.type = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
                params.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;

//                params.token = this;
                wm.addView(tv, params);
            } catch (IOException e) {
                e.printStackTrace();
            }
            LogUtils.w(new Date() + " ### end |||||||||||");
        }
    }

至于,为什么还可以更新 UI ,我。。。应该说 view 本身就没有规定只能在主线程更新,只要子线程更新需要满足跟主线程同样的条件,都可以更新了。(欢迎深究)