zoukankan      html  css  js  c++  java
  • Android中的Handle(句柄)

    一、Handle(句柄)是什么?

    (1)、结合线程所在消息队列来更新用户界面(UI)的一套消息处理机制 

    (2)、Handle消息传递机制流程图

    由以上可知:主线程无法处理时间比较繁长的任务,需要子线程进行处理,而子线程无法进行用户界面(UI)更新,需要使用handler来传递消息给主线程,让主线程完成用户界面(UI)更新。由于主线程和子线程进行不同的时间工作,所以需要用MessageQueue来存放子线程的消息,让Looper取出消息交给主线程响应。

    二、Handle(句柄)有什么用?

     接受子线程发送的数据, 并用此数据配合主线程更新用户界面(UI),用于线程间的通讯。通俗点的解释:当一个应用程序打开的时,Android系统首先会开启一个主线程(即UI线程)。UI线程主要是管理界面上的那些控件,如:文本框,编辑框,按钮等。当点击一个按钮时,用户界面(UI)线程就会分发事件到按钮上,以此来响应接下来的操作(如要绘制一个图,显示一个美女等等)。而如果这个图特复杂,或者这个美女画质特别高(一般画质特别高,即像素特别高,也就是同样大小的方块中,像素点特别特别的多,简单点就是这张图片特别大),此时线程就会为了这个而进行计算,如果5秒钟内还没有计算完的话,界面就会出现假死现象,因为Android系统的Acitivity响应时间为5秒,超过了就要出问题(弹出一个“强制关闭”的对话框)。如果我们把这种耗时的操作放在子线程,就要好的多了。当子线程计算完了(不管花了多久),此时只要发一个消息给主线程,告诉它计算完了,准备好了,那么主线程就可以直接进行绘制或者显示了。为什么不干脆绘制或者将显示的工作放在子线程中进行呢?因为界面只有一个,而这个界面的有关操作已经纳入了主线程中,所以如果子线程要去更改界面的内容的话,就会出现问题。也就是说更新UI只能在主线程中。而Handler的作用就是接收子线程完成耗时操作反馈回来的信息,并用此数据配合主线程更新用户界面(UI)。文艺点的解释:一个正在唱歌的女郎(主线程用户界面(UI)),语音播报(按了一个按钮之类的)下一个节目是吉它表演(按钮的监听事件),此时这个吉它就要后台的人来为她准备,因为她正在唱着歌呢。这时后台的人发现吉它找不到了(耗时操作),怎么办?时间是很宝贵的,如果继续唱歌,难免会被会质疑的,因此,当她唱完歌时,只能跳到下下个节目跳舞的表演(主线程继续往下走),而后台的人则拼命的去找吉它(使用子线程进行耗时操作)。终于,后台的人告诉她“吉它”找到了(收到子线程的反馈信息)。她立马结束了当前的节目。因为之前连表演了好几个节目(不耗时的操作),但人们最期待的还是它的吉它表演。于是,她拿上后台给她的吉它开始表演起吉它演奏来(进行主线程更新操作)。

    三、Handle(句柄)咋么用?

    以下是使用Handler和线程制作简单的计时器部分代码解释,如下所示。

    (1)、新建Handle如下所示 

       private  Handler handler=new Handler()
    { @Override
    public void handleMessage(Message msg)
    {
    super.handleMessage(msg); } };

    (2)、从子线程中发出消息如下所示 

    Message message=handler.obtainMessage();
    message.what=1;
    message.arg0=i;
    message.obj="倒计时:";
    handler.sendMessage(message);

    (3)、在Handler中捕获所需消息,实现响应。如下所示 。

       private  Handler handler=new Handler()
    {
        @Override
        public void handleMessage(Message msg) 
     {
         super.handleMessage(msg);
         int arg0=msg.arg0;
         String info= (String) msg.obj;
         if (msg.what==1)
       {
          textView.setText(info+arg0);
         }
         if (arg0==0)
       {
          textView.setText("完成");
         }
        }
       };

    (4)、在逻辑编程文件MainActivity.java中获取用户界面布局文件activity_main.xml下的控件id,如下所示。

    private Button button;
    private TextView textView;
    private EditText editText;
       private void BlindID() 
    {
        button=findViewById(R.id.button);
        textView=findViewById(R.id.textView);
        editText=findViewById(R.id.editText);
        button.setOnClickListener(this);
       }

    (5)、在逻辑编程文件MainActivity.java中创建Handle(句柄),让逻辑编程文件MainActivity.java中的子线程通过Handle(句柄)来传递时间变化给主线程,从而让主线程来更新用户界面倒计时的时间变化,如下所示。

       private  Handler handler=new Handler()
    { @Override
    public void handleMessage(Message msg)
    {
    super.handleMessage(msg);
    } };

    (6)、在逻辑编程文件MainActivity.java中设置好监听事件,从EditText中获取所要设定的时间,需创建int型来获取存放用户所输入的数字,将显示的TextView设置为倒计时+数字,利用for循环来改变数字,并创建一个新子线程来实现读秒,让子线程睡上一秒后发送新的信息。如下所示。 

    private int num1;
    private String num;
       public void onClick(View view) 
    {
    switch (view.getId())
    {
    case R.id.button: num=editText.getText().toString(); num0=Integer.parseInt(num); textView.setText("倒计时:"+num0); new Thread(new Runnable()
    { @Override
    public void run()
    {
    for (int i=num0;i >=0;i--)
    {
    try
    { Thread.sleep(
    1000);//实现读秒 }
    catch (InterruptedException e)
    { e.printStackTrace(); } Message message
    =handler.obtainMessage(); message.what=1; message.arg0=i; message.obj="倒计时:"; handler.sendMessage(message);//发送信息 } } }).start(); break; } }

    (7)、逻辑编程文件MainActivity.java中主线程捕获子线程传来的时间变化信息,响应TextView设置,让用户界面(UI)实现每隔一秒改变倒计时数字的更新,如下所示。 

       private  Handler handler=new Handler()
    { @Override
    public void handleMessage(Message msg)
    {
    super.handleMessage(msg); int arg0=msg.arg0; String info= (String) msg.obj; if (msg.what==1)
    { textView.setText(info
    +arg0); } if (arg0==0)
    { textView.setText(
    "完成"); } } };

     以下是使用Handler和线程制作简单的计时器全部代码,如下所示。

    (1)、逻辑编程文件MainActivity.java如下所示

    package com.example.CountDownDemo;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
       public class MainActivity extends AppCompatActivity implements View.OnClickListener 
    {
    private Button button; private TextView textView; private EditText editText; private int num0; private String num; private Handler handler=new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); int arg0=msg.arg0; String info= (String) msg.obj; if (msg.what==1) { textView.setText(info+arg0); } if (arg0==0) { textView.setText("完成"); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BlindID(); } private void BlindID() { button=findViewById(R.id.button); textView=findViewById(R.id.textView); editText=findViewById(R.id.editText); button.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.button: num=editText.getText().toString(); num0=Integer.parseInt(num); textView.setText("倒计时:"+num0); new Thread(new Runnable() { @Override public void run() { for (int i=num0;i >=0;i--) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Message message=handler.obtainMessage(); message.what=1; message.arg0=i; message.obj="倒计时:"; handler.sendMessage(message); } } }).start(); break; } } }

    (2)、用户界面布局文件activity_main.xml如下所示

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      tools:context="com.example.CountDownDemo.MainActivity">
      <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="输入计时时间:"
          android:textSize="20sp"/>
        <EditText
          android:id="@+id/editText"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:hint="请输入数字"
          android:numeric="integer"/>
      </LinearLayout>
      <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#000"/>
      <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="倒计时:**"
        android:textSize="20sp"
        android:gravity="center"/>
      <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="开始计时"/>
    </LinearLayout>

    (3)、字符串资源文件strings.xml如下所示

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
      <string name="app_name">CountDownDemo</string>
      <string name="name">count_down</string>
    </resources>

    (4)、R.java文件如下所示

    /* AUTO-GENERATED FILE.  DO NOT MODIFY.
     *
     * This class was automatically generated by the
     * aapt tool from the resource data it found.  It
     * should not be modified by hand.
     */
    package com.example.CountDownDemo;
      public final class R 
    {
       public static final class array 
     {
       }
       public static final class attr
     {
       }
       public static final class drawable 
     {
        public static final int ic_launcher=0x7f020000;
       }
       public static final class id 
     {
        public static final int button=0x7f070001;
        public static final int textView=0x7f070002;
        public static final int editText=0x7f070003;
       }
       public static final class layout 
     {
        public static final int activity_main=0x7f030000;
       }
       public static final class string 
     {
        public static final int app_name=0x7f050000;
        public static final int hello_world=0x7f050001;
       }
       public static final class style 
     {
        public static final int AppTheme=0x7f060000;
       }
     } 

    (5)、功能清单配置文件AndroidManifest.xml如下所示

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.CountDownDemo"
      android:versionCode="1"
      android:versionName="1.0" >
      <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="10" />
        <application
          android:allowBackup="true"
          android:icon="@drawable/ic_launcher"
          android:label="@string/app_name"
          android:theme="@style/AppTheme" >
        <activity
          android:name="com.example.CountDownDemo.MainActivity"
          android:label="@string/app_name" >
          <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
        </activity>
       </application>
    </manifest>

    (6)、效果图如下所示

  • 相关阅读:
    跨域名登录态传递
    ECC公钥格式详解
    企业应用架构演化探讨:从微服务到Service Mesh
    阿里云宕机故障
    一个“三无管理者”的思考
    如何构建安全的微服务应用
    微服务架构实践
    Redis持久化之RDB
    Redis持久化persistence
    Redis 缓存失效和回收机制续
  • 原文地址:https://www.cnblogs.com/AChenWeiqiangA/p/13170200.html
Copyright © 2011-2022 走看看