Android中子线程和UI线程通信详解

Android中子线程和UI线程之间通信的详细解释

1.在多线程编程这块,我们经常要使用Handler,Thread和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢?下面详解一下。
2.首先在开发Android应用时必须遵守单线程模型的原则:
Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。
3.Handler:
(1).概念:
Handler是沟通Activity 与Thread/runnable的桥梁。而Handler是运行在主UI线程中的,它与子线程可以通过Message对象来传递数据。
(2).使用:
A:Handler是运行在UI线程中,主要接收子线程发送的数据信息, 并用此数据配合主线程更新UI,用来跟UI主线程交互用。比如可以用handler发送一个message,然后在handler的线程中来接收、处理该消息。
B:消息的处理者。通过Handler对象我们可以封装Message对象,然后通过sendMessage(msg)把Message对象添加到MessageQueue中;当MessageQueue循环到该Message时,就会调用该Message对象对应的handler对象的handleMessage()方法对其进行处理。
C:Handler可以分发Runnable对象,也可以分发Message对象。

4.Message:
 消息对象,顾名思义就是记录消息信息的类。也就是说是信息的载体,存放信息内容。这个类有几个比较重要的字段:

  (1).arg1和arg2:我们可以使用两个字段用来存放我们需要传递的整型值,在Service中,我们可以用来存放Service的ID。
  (2).obj:该字段是Object类型,我们可以让该字段传递某个对象到消息的接受者中。
  (3).what:这个字段可以说是消息的标志,判断是接收了哪个消息。在消息处理中,我们可以根据这个字段的不同的值进行不同的处理,类似于我们在处理Button事件时,通过switch(v.getId())判断是点击了哪个按钮。
Android推荐通过Message.obtain()或者Handler.obtainMessage()获取Message对象。这并不一定是直接创建一个新的实例,而是先从消息池中看有没有可用的Message实例,存在则直接取出并返回这个实例。反之如果消息池中没有可用的Message实例,则根据给定的参数new一个新Message对象。通过分析源码可得知,Android系统默认情况下在消息池中实例化10个Message对象。
5.源码展示:
(1).activity_main.xml布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="自定义Thread继承Thread" /> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="自定义Runnable实现Runnable" /> <Button android:id="@+id/btn3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="定时更新UI界面,Handler分发Runnable对象" /> <Button android:id="@+id/btn4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="定时更新UI界面,Handler分发Message对象" /> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0" /> </LinearLayout>

(2).MainActivity.java

package com.chengdong.su.threaddemo; import com.chengdong.su.threaddemo.util.MyRunnable; import com.chengdong.su.threaddemo.util.MyThread; import android.R.integer; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity implements OnClickListener { /** TAG */ private final String TAG = getClass().getSimpleName(); /** the object of the button */ private Button mButton; /** the object of the button */ private Button mButton2; /** the object of the button */ private Button mButton3; /** the object of the button */ private Button mButton4; /** the object of the TextView */ private TextView mTextView; /** 计数 */ private int mCount = 0; /** 标志 */ private int MESSAGE_FLAG = 1; /** * Handler分发Runnable对象的方式 */ private Handler mHandler = new Handler(); Runnable runnable = new Runnable() { @Override public void run() { mCount++; mHandler.postDelayed(runnable, 1000); mTextView.setText(mCount + ""); } }; /*** * Handler分发Message对象的方式 */ Handler mHandler2 = new Handler() { public void handleMessage(android.os.Message msg) { if (msg.what == 1) { mTextView.setText("Handler分发Message对象的方式"); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } /** * 初始化组件对象 */ private void initView() { mButton = (Button) findViewById(R.id.btn); mButton2 = (Button) findViewById(R.id.btn2); mButton3 = (Button) findViewById(R.id.btn3); mButton4 = (Button) findViewById(R.id.btn4); mButton.setOnClickListener(this); mButton2.setOnClickListener(this); mButton3.setOnClickListener(this); mButton4.setOnClickListener(this); mTextView = (TextView) findViewById(R.id.tv); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn: { // 方法一:继承的方式:自定义Thread继承Thread,开启一个新的线程 new MyThread().start(); break; } case R.id.btn2: { // 方法二:实现的方式:implement Runnable new Thread(new MyRunnable()).start(); break; } // 方法三:handler分发Runnable对象:定时更新UI界面 提交计划任务马上执行 case R.id.btn3: { // Handler分发Runnable对象 mHandler.post(runnable); break; } // 方法四:Handler分发Message对象 ,定时更新UI界面 提交计划任务马上执行 case R.id.btn4: { // 不推荐这种方式 // Message msg = new Message(); // 推荐使用这种获取对象的方式:从消息池中获得可用的Message对象 Message msg = Message.obtain(); msg.what = MESSAGE_FLAG; mHandler2.sendMessage(msg); break; } default: break; } } }

(3).MyRunnable.java

package com.chengdong.su.threaddemo.util; import android.util.Log; /*** * 自定义一个MyRunnable线程 * * @author scd * */ public class MyRunnable implements Runnable { public MyRunnable() { super(); } /** TAG */ private final String TAG = getClass().getSimpleName(); @Override public void run() { for (int i = 0; i < 20; i++) { Log.e(TAG, Thread.currentThread().getName() + ",实现的方法" + i); } } }

(4)MyThread.java

package com.chengdong.su.threaddemo.util; import android.util.Log; /*** * 自定义一个线程 * * @author scd * */ public class MyThread extends Thread { public MyThread() { super(); } /** TAG */ private final String TAG = getClass().getSimpleName(); @Override public void run() { super.run(); for (int i = 0; i < 10; i++) { Log.e(TAG, Thread.currentThread().getName() + ",继承Thread类:" + i); } } }

时间: 2024-12-22 01:35:25

Android中子线程和UI线程通信详解的相关文章

Android中子线程和UI线程通信详解_Android

Android中子线程和UI线程之间通信的详细解释 1.在多线程编程这块,我们经常要使用Handler,Thread和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢?下面详解一下. 2.首先在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行. 3.Handler: (1).概念: Handler是沟通Activity 与Thread/runnable的桥梁.而Handler是运行在主UI线程中的,它与子线程

详解Android中OkHttp3的例子和在子线程更新UI线程的方法

okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿.就是唯一可以更新UI的线程.这个只是点会在给okHttp填坑的时候用到.而且,这个内容本身在日常的开发中也经常用到,值得好好学一学. okHttp发起同步请求 第一个列子是一个同步请求的例子. private void performSyncHttpRequest() { OkHttpClient

Android Socket通信详解_Android

一.Socket通信简介  Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是"请求-响应方式",即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据.而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求. 那么,什么是socket?Socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信.通过

OkHttp3几个简单的例子和在子线程更新UI线程的方法

okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿.就是唯一可以更新UI的线程.这个只是点会在给okHttp填坑的时候用到.而且,这个内容本身在日常的开发中也经常用到,值得好好学一学. okHttp发起同步请求 第一个列子是一个同步请求的例子. private void performSyncHttpRequest() { OkHttpClient

Android UI 实现老虎机详解及实例代码

Android UI 实现老虎机详解 listview 的使用步骤 简单的listview老虎机实现 1.实现效果图 2.需要掌握的知识 listview的使用步骤 listview的Adapter接口的实现 listview中的MVC 3.知识详解 ListView 是一个控件,一个在垂直滚动的列表中显示条目的一个控件,这些条目的内容来自于一个ListAdapter .EditText Button TextView ImageView Checkbox 五大布局. 1.布局添加Listvie

Android 网络html源码查看器详解及实例

Android 网络html源码查看器详解及实例 IO字节流的数据传输了解 Handler的基本使用 1.作品展示 2.需要掌握的知识 FileInputStream,FIleOutputStream,BufferInputStream,BufferOutStream的读写使用与区别 //进行流的读写 byte[] buffer = new byte[1024 * 8]; //创建一个写到内存的字节数组输出流 ByteArrayOutputStream byteArrayOutputStream

Android 中Lambda表达式的使用实例详解

Android 中Lambda表达式的使用实例详解 Java8 中着实引入了一些非常有特色的功能,如Lambda表达式.streamAPI.接口默认实现等等.Lambda表达式在 Android 中最低兼容到 Android2.3 系统,兼容性还是不错的,Lambda表达式本质上是一种匿名方法,它既没有方法名,也没有访问修饰符和返回值类型,使用它编写的代码将更加简洁易读. 1.Lambda表达式的基本写法 如果想要在 Android 项目中使用 Lambda表达式 或者 Java8 的其他新特性

Android 消息分发使用EventBus的实例详解

Android 消息分发使用EventBus的实例详解 1. AndroidStudio使用 dependencies { //最新版本 compile 'org.greenrobot:eventbus:3.0.0' //可以翻倍提高EventBus使用效率 provided 'de.greenrobot:eventbus-annotation-processor:3.0.0-beta1' } 2. 在基类Activity中配置 /** * Activity基类 */ protected Eve

Android 蓝牙2.0的使用方法详解_Android

本文为大家分享了Android操作蓝牙2.0的使用方法,供大家参考,具体内容如下 1.Android操作蓝牙2.0的使用流程 (1)找到设备uuid (2)获取蓝牙适配器,使得蓝牙处于可发现模式,获取下位机的socket,并且与上位机建立建立连接,获取获取输入流和输出流,两个流都不为空时,表示连接成功.否则是连接失败. (3).与下位机的socket开始通信. (4).通信结束后,断开连接(关闭流,关闭socket) 2接下来接直接上代码:2.1找到设备uuid(一般厂商都会给开发者提供) 复制