`
XiangdongLee
  • 浏览: 91303 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

【攻克Android(25)】HandlerThread

 
阅读更多
本文围绕以下两个部分展开:

一、HandlerThread
案例一:通过HandlerThread进行线程间通信(非 UI进程更新 UI、处理耗时任务)





一、HandlerThread

        1. new Thread(){...}.start()启动线程 和 使用 Handler 启动线程的不好之处:

        (1)new Thread(){...}.start()启动线程:

                多次使用这种方式,会创建多个匿名线程。使得程序运行起来越来越慢。

        (2)使用 Handler 启动线程:

                使用一个Handler来启动一个线程,当该线程不再使用就删除,保证线程不会重复创建。

                但是,这样创建的handler是在主线程即UI线程下的Handler,即这个Handler是与UI线程下的默认Looper绑定的。因此,如果是默认创建Handler,那么如果线程是做一些耗时操作如网络获取数据等操作,这样创建Handler是不行的。

        2. 使用 HandlerThread:

        (1)HandlerThread:

                Handy class for starting a new thread that has a looper.The looper can then be used to create handler classes. Note that start() must still be called.

                HandlerThread实际上就一个Thread,只不过它比普通的Thread多了一个Looper。

        (2)创建的Handler对象是与HandlerThread这个线程绑定了(这时就不再是与UI线程绑定了,这样它处理耗时操作将不会阻塞UI)。


案例一:通过HandlerThread进行线程间通信(非 UI进程更新 UI、处理耗时任务)

        效果如下:

        进入主界面后如下:



        点击按钮后,星形进度条和文本按每秒增加10的速率,一直增加到100。











        (1)strings.xml

<string name="btn_start">Start</string>


        (2)activity_main.xml。布局:一个开始按钮,一个星形进度条,一个文本进度。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="@string/btn_start" />

    <RatingBar
        android:id="@+id/ratingBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/btnStart"
        android:visibility="gone" />

    <TextView
        android:id="@+id/tvScale"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/ratingBar"
        android:visibility="gone" />

</RelativeLayout>

<!-- 1. -->
<!-- RatingBar 和 TextView 是不可见的,
当点击 Start 按钮的时候,才设置为可见。 -->


        (3)MainActivity。通过HandlerThread进行线程间通信(非 UI进程更新 UI、处理耗时任务)

package com.android.handlerthread;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.RatingBar;
import android.widget.TextView;


public class MainActivity extends Activity {
    // 3.1 要用到主界面中的 RatingBar 和 TextView,因此要先声明并初始化。
    // 声明两个控件(RatingBar 和 TextView)
    private RatingBar ratingBar;
    private TextView tvScale;
    // 5.1
    private MyHandlerThread handlerThread;
    private Handler handler;

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

        // 3.2 初始化两个控件(RatingBar 和 TextView)
        ratingBar = (RatingBar) findViewById(R.id.ratingBar);
        tvScale = (TextView) findViewById(R.id.tvScale);

        // 5.2 实例化 HandlerThread 的子类:MyHandlerThread,
        //     并启动线程(调用start方法),线程就绪
        //     "HandlerThread"是名称,随便写字符串都可以。
        handlerThread = new MyHandlerThread("HandlerThread");
        handlerThread.start();

        // 6. 必须用到 handler 构造器:
        // 原因:需要把callback传入,
        // 从而使自己的 HandlerThread 的 handleMessage 来替换掉 Handle原生的 handleMessage

        // 参数一:If this thread has been started,
        // this method will block until the looper has been initialized.
        //        若线程已启动,则锁定此方法直到 Looper 初始化完成
        // 参数二:handlerThread是实现了 Handler 回调接口(Handler.Callback)的线程对象,
        //        从而 handler 可运行 handleMessage() 方法
        handler = new Handler(handlerThread.getLooper(), handlerThread);
    }

    /**
     * 2.
     *
     * @param view
     */
    public void onClick(View view) {
        // 7. 当点击Start按钮的时候,设置控件可见,并让 handler 发送空消息
        ratingBar.setVisibility(View.VISIBLE);
        tvScale.setVisibility(View.VISIBLE);
        handler.sendEmptyMessage(1);
    }

    /**
     * 4. 自定义 HandlerThread 的子类
     *
     */
    /**
     * Handler.Callback:回调接口
     * <p/>
     * Callback interface you can use when instantiating a Handler to avoid
     * having to implement your own subclass of Handler.
     * <p/>
     * 如果Callback不为空,则消息就在它实现的这个接口的 handleMessage()方法里处理。
     */
    private class MyHandlerThread extends HandlerThread
            implements Handler.Callback {
        /**
         * 4.1 必须初始化父类(HandlerThread)的构造方法(先构造出父类,才能产生子类)
         * <p/>
         * 因为 HandlerThread 父类,只带有一个含参的构造方法,没有无参构造方法,
         * 因此,要产生子类,必须先构造父类。
         * 构造父类需要含参构造方法,因此子类也必须实现含参的构造方法。
         */
        public MyHandlerThread(String name) {
            super(name);
        }

        /**
         * 4.2实现接口(Handler的回调接口)的方法
         *
         * @param msg
         * @return
         */
        @Override
        public boolean handleMessage(Message msg) {
            // 进度条总数为 100
            final int total = 100;
            // 初始进度为 0
            int current = 0;
            while (current <= total) {
                try {
                    // 可以在此处完成具体的任务
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // 4.2.1 计算进度刻度
                // 之所以定义成 final,是因为下面的 内部类 new Runnable里面要用
                // (防止内部类里面对它进行修改)

                // 5颗 RatingBar的星星,要运行完 100进度,因此每次填充星星的速率是:0.05
                final float rating = (float) (current * 0.05);
                final int innerCurrent = current;
                // 让当前进度每次增加 10,那么 rating 每次就增加 0.5个星星
                current += 10;

                // 4.2.2 加入消息队列,运行 UI 线程更新界面
                ratingBar.post(new Runnable() {
                    // new Runnable中,run方法运行完,线程就销毁掉了
                    @Override
                    public void run() {
                        // 更新界面中的 ratingBar,更新进度条刻度
                        ratingBar.setRating(rating);
                    }
                });
                tvScale.post(new Runnable() {
                    @Override
                    public void run() {
                        // 更新进度文本 (当前进度 / 进度条总数)
                        tvScale.setText(String.format("%d / %d", innerCurrent, total));
                    }
                });
            }
            // True if no further handling is desired
            return true;
        }
    }

    // ---------------------------------------------------------------
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
  • 大小: 14.8 KB
  • 大小: 24 KB
  • 大小: 24.4 KB
  • 大小: 18.3 KB
  • 大小: 18.5 KB
  • 大小: 18.3 KB
分享到:
评论

相关推荐

    Android实例HandlerThread源码分析

    本篇文章主要给大家通过实例代码分析了Android中HandlerThread的用法以及步骤,需要的朋友参考学习下吧。

    Android HandlerThread 全面解析

    `HandlerThread`是Android提供的一种特殊线程类,它结合了线程和消息处理机制,使得开发者能够更方便地在后台执行耗时操作,同时与主线程进行通信。本文将全面解析`HandlerThread`的工作原理、使用方法以及它在实际...

    android HandlerThread 实例

    在Android开发中,`HandlerThread` 是一个非常重要的组件,特别是在处理异步任务和线程通信方面。`HandlerThread` 是一个内置了Looper的线程,它可以为长时间运行的任务提供一个独立的消息处理循环,避免阻塞主线程...

    HandlerThread的使用与自定义HandlerThread

    在Android开发中,`HandlerThread` 是一个非常重要的组件,尤其在处理异步任务和线程间通信时。本文将深入探讨 `HandlerThread` 的使用、工作原理,并讲解如何自定义 `HandlerThread`,以及为什么在某些场景下我们...

    android HandlerThread 使用demo

    在Android开发中,`HandlerThread` 是一个非常重要的线程管理工具,它结合了线程和消息处理机制,常用于创建后台线程处理耗时任务,以避免阻塞主线程,提升用户体验。本示例("android HandlerThread 使用demo")将...

    Android-kotlin实现网络请求库

    本项目"Android-kotlin实现网络请求库"是基于Kotlin构建的一个自定义网络请求库,结合了fastjson用于数据解析,HandlerThread来管理后台任务,以及自定义注解以提升代码的可读性和易用性。下面我们将详细探讨这些...

    Android HandlerThread使用方法详解

    Android HandlerThread使用方法详解 HandlerThread 继承自Thread,内部封装了Looper。 首先Handler和HandlerThread的主要区别是:Handler与Activity在同一个线程中,HandlerThread与Activity不在同一个线程,而是别外...

    HandlerThread

    【HandlerThread】是一种在Android系统中专为处理后台任务而设计的线程类。它继承自`Thread`,并结合了`Looper`和`Handler`的概念,使得开发者可以在子线程中创建一个消息循环,方便地处理来自主线程或其他线程的...

    实例分析Android中HandlerThread线程用法

    一、HandlerThread的介绍及使用举例  HandlerThread是什么鬼?其本质就是一个线程,但是HandlerThread在启动的时候会帮我们准备好一个Looper,并供外界使用,说白了就是使我们在子线程中更方便的使用Handler,比如...

    深入Android HandlerThread 使用及其源码完全解析

    HandlerThread是Android系统提供的一种线程管理工具,它在Android应用程序开发中扮演着重要的角色,尤其是在处理长时间运行的任务和保持线程的持续性方面。在Android的消息机制中,Handler、MessageQueue和Looper三...

    Android HandlerThread的使用及原理详解

    在Android开发中,`HandlerThread` 是一个非常重要的组件,它结合了线程(Thread)和消息处理(Handler)的功能,使得开发者可以在后台线程中高效地处理异步任务,尤其是那些需要定时或周期性执行的操作。...

    Android用HandlerThread模拟AsyncTask功能(ThreadTask)

    【Android HandlerThread 模拟 AsyncTask 功能(ThreadTask)】 在Android开发中,AsyncTask是一个用于在后台线程执行任务并更新UI的工具类,但在某些特定情况下,如大量并发任务或者需要更精细的线程控制时,...

    Android:Handler学习实例2(HandlerThread、Bundle传递参数)

    HandlerThread handlerThread = new HandlerThread("handler_thread"); //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start()方法,否则获得的值为空值; handlerThread.start(); //创建...

    android使用handlerthread创建线程示例

    本文将深入探讨如何使用`HandlerThread`在Android中创建线程,以及为什么相较于直接使用`Thread`类,`HandlerThread`更具有优势。 首先,让我们理解一下`Thread`类的基本使用。通常,我们可以通过创建一个新的匿名...

    handlerthread学习demo

    在Android开发中,`HandlerThread` 是一个非常重要的组件,特别是在处理异步任务和线程同步方面。`HandlerThread` 是一个内置了消息队列和Looper的线程,它的主要作用是提供一个稳定的、可控制的后台执行环境,用于...

Global site tag (gtag.js) - Google Analytics