Android通过子线程更新UI的几种方式

时间:2021-08-24 22:30:06

一般情况下,UI的更新都少不了Handler,首先我们先了解一下Handler机制:

Handler消息机制

定义

Message

线程间通信的数据单元,可通过message携带需要的数据创建对象:Message.obtain(what)

Handler

Handler是Message的处理器,同时也负责消息的发送和移除工作

发送即时消息:即使发送即时处理

发送延时消息:即时发送,过一会儿处理

MessageQueue:消息队列

用来存放通过Handler发送的消息,它是一个按Message的when排序的优先级队列

Looper:循环器

负责循环取出Message Queue里面的当前需要处理的Message,交给对应的Handler进行处理,处理完后,将Message缓存到消息池中,以备复用

Handler的基本使用

步骤:

①创建Handler成员变量,并重写其handleMessage()

②在分线程创建Message对象

③使用handler对象发送Message

④在handleMessage()中处理消息

消息机制原理

Android通过子线程更新UI的几种方式

文字描述

从handler中获取一个消息对象,把数据封装到消息对象中,通过handler的send方法把消息push到MessageQueue队列中,looper对象会轮询MessageQueue队列,把消息对象取出。通过dispatchMessage分发给Handler,再回调用Handler实现的handleMessage方法处理消息。

接下来,我们再看在通过子线程更新UI常见的几种方式

通过子线程更新UI

首先我们要理解子线程可不可以更新UI,谷歌官方的说法是:一定要在主线程更新UI。

这是为什么?

如果多个线程更新UI,很容易造成整个界面的UI出错。

那为什么又有通过子线程更新UI这种说法呢?

当我们需要进行耗时操作时(如联网等),如果放在主线程,会对整个应用造成极大的负担,用户体验极差,所以我们就通过Handler机制新开辟一个线程,耗时操作交给子线程,UI的更新实际还是主线程来实现的。

所以严谨来说是通过子线程更新UI,而不是子线程更新UI。

通过子线程更新UI

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button update_handler;
private Button update_ViewPost;
private Button update_handlerPost;
private Button update_handlerPostDelay;
private Button update_RunOnUiThread;
private Button update_AsyncTask;
private TextView textView; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
} private void initView() {
update_handler=findViewById(R.id.button1);
update_ViewPost=findViewById(R.id.button2);
update_handlerPost=findViewById(R.id.button3);
update_handlerPostDelay=findViewById(R.id.button4);
update_RunOnUiThread=findViewById(R.id.button5);
update_AsyncTask=findViewById(R.id.button6);
textView=findViewById(R.id.myword); update_handler.setOnClickListener(this);
update_ViewPost.setOnClickListener(this);
update_handlerPost.setOnClickListener(this);
update_handlerPostDelay.setOnClickListener(this);
update_RunOnUiThread.setOnClickListener(this);
update_AsyncTask.setOnClickListener(this); } @Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button1:
update_handler(); break;
case R.id.button2:
update_ViewPost();
break;
case R.id.button3:
update_handlerPost();
break;
case R.id.button4:
update_handlerPostDelay();
break;
case R.id.button5:
update_RunOnUiThread();
break;
case R.id.button6:
new updateAsyncTask().execute();
break;
} } Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what==1){
textView.setText("小慕慕");
}
}
};
/*
方法1
*/
private void update_handler(){
new Thread(new Runnable() {
@Override
public void run() {
Message message=handler.obtainMessage();
message.what=1;
handler.sendMessage(message); }
}).start(); }
/*
方法2
*/
private void update_ViewPost(){
new Thread(new Runnable() {
@Override
public void run() {
textView.post(new Runnable() {
@Override
public void run() {
textView.setText("小九九");
}
}); }
}).start();
}
/*
方法3
*/ private void update_handlerPost() {
new Thread(new Runnable() {
@Override
public void run() {
handler.post(new Runnable() {
@Override
public void run() {
textView.setText("小酒酒");
}
});
}
}).start();
}
/*
方法4
*/
private void update_handlerPostDelay(){
new Thread(new Runnable() {
@Override
public void run() {
handler.postDelayed(new Runnable() {
@Override
public void run() {
textView.setText("九酒");
}
},3000);
}
}).start();
}
/*
方法5
*/
private void update_RunOnUiThread(){
new Thread(new Runnable() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText("慕九");
}
}); }
}).start();
}
/*
方法6
*/
class updateAsyncTask extends AsyncTask<String,Integer,String>{ @Override
protected void onPreExecute() {
super.onPreExecute();
} @Override
protected String doInBackground(String... strings) { publishProgress();
return null;
} @Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
} @Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
textView.setText("结束");
}
} }

布局文件

<?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=".MainActivity"
> <Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="handler"
android:textAllCaps="false"
/> <Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="View.post()"
android:textAllCaps="false"
/> <Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="handlerPost()"
android:textAllCaps="false"/> <Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center_horizontal"
android:text="handlerPostDelay()"
android:textAllCaps="false"/>
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center_horizontal"
android:text="runOnUiThread()"
android:textAllCaps="false"/> <Button
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_gravity="center_horizontal"
android:text=" update_AsyncTask()"
android:textAllCaps="false"/> <TextView
android:id="@+id/myword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="慕九酒"/> </LinearLayout>

运行结果:

Android通过子线程更新UI的几种方式

总结

其实这六种方式并没有太大的区别,前五种方式都是基于第一种方式的封装,都是采用的Thread+handler模式,第六种封装的更厉害了些,它是Thread+hanler+Threadpool。上面的代码示例中有些看起来完全是在子线程更新的UI,实际上这是因为做的封装让我们看着好像是在子线程更新UI似的,实际上如果我们查看源码,就会发现它还是通过handler机制在主线程更新的UI.

参考https://blog.csdn.net/oheg2010/article/details/93092541

Android通过子线程更新UI的几种方式的更多相关文章

  1. Android可以子线程更新UI?

    初了解Android的时候,就知道Android是不能在子线程更新UI的,不然程序会直接抛出异常,告诉你,别给我在自线程搞事情! 但是,这个是针对普通的view做的限制,而TextureView,Su ...

  2. android基础----&gt&semi;子线程更新UI

    和许多其他的GUI 库一样,Android 的UI 也是线程不安全的.也就是说,如果想要更新应用程序里的UI 元素,则必须在主线程中进行,否则就会出现异常.了解AsyncTask的用法,请参见我的博客 ...

  3. Android开发——子线程操作UI的几种方法

    在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法: 在看方法之前需要了解一下Android中的消息机制. 转载请标明出处:h ...

  4. iOS子线程更新UI的两种方法

    http://blog.csdn.net/libaineu2004/article/details/45368427 方法1:performSelectorOnMainThread[self perf ...

  5. Android开发——子线程操作UI的几种方法&lpar;待续&rpar;

    方法2  Handler andler mHandler = new Handler() { @Override public void handleMessage(Message msg) { su ...

  6. Android子线程更新UI的方法总结

    版权声明:本文为博主原创文章,转载请注明出处:https://i.cnblogs.com/EditPosts.aspx?postid=6121280 消息机制,对于Android开发者来说,应该是非常 ...

  7. &lbrack;Android学习笔记&rsqb;子线程更新UI线程方法之Handler

    关于此笔记 不讨论: 1.不讨论Handler实现细节 2.不讨论android线程派发细节 讨论: 子线程如何简单的使用Handler更新UI 问题: android开发时,如何在子线程更新UI? ...

  8. android子线程更新UI

    参考:https://www.cnblogs.com/joy99/p/6121280.html 子线程是不能直接更新UI的.Android实现View更新有两组方法,分别是invalidate和pos ...

  9. Android子线程更新UI成功

    android子线程更新UI成功 今天在写demo的时候,在子线程中更新UI,发现更新成功,记录一下. protected void onCreate(Bundle savedInstanceStat ...

随机推荐

  1. C语言之进制

    进制 一种计数的方式.侧重点在于计数的时候是逢多少进一. 1)      C语言可以识别的进制 二进制 每一位. 0 0 1 0 0 1 1 0 1 0 1 0 0 1 0 1 1 0 在C语言中,写 ...

  2. Github 开源:高效好用的对象间属性拷贝工具:升讯威 Mapper( Sheng&period;Mapper)

    Github 地址:https://github.com/iccb1013/Sheng.Mapper 对象属性值映射/拷贝工具.不需要创建映射规则,不要求对象类型一致,适用于简单直接的拷贝操作,可以全 ...

  3. Qwtpolar的编译

    Qwtpolar是Qt的一个第三方扩展,用于绘制极坐标下的函数图形.官方网站在: http://sourceforge.net/projects/qwtpolar/ 新版的QGIS2.8依赖这个库,所 ...

  4. VisualStudio移动开发(C&num;、VB&period;NET)Smobiler开发平台——ImageTabBar控件的使用方式

    一.          样式一 我们要实现上图中的效果,需要如下的操作: 从工具栏上的“Smobiler Components”拖动一个ImageTabBar控件到窗体界面上 修改ImageTabBa ...

  5. Codeforces 852I Dating 树上莫队

    Dating 随便树上莫队搞一搞就好啦. #include<bits/stdc++.h> #define LL long long #define LD long double #defi ...

  6. matlab-双摆仿真

    在物理学和数学中,在动力系统领域,双摆是一个摆锤,另一个摆锤连接在其末端,是一个简单的物理系统,具有丰富的动态特性,对初始条件具有很强的敏感性.双摆的运动由一组耦合的常微分方程控制并且是混沌的. 由于 ...

  7. 【工具相关】ionic-通过nmp安装最新版本的 cordova 和 ionic

    一,命令行下输入: sudo npm install -g cordova ionic 用来安装最新版本的cordova和ionic. 如下图所示: 二,等待一下,如下图所示. 三,用命令 npm u ...

  8. log4j。日志输出

    log4j.rootLogger = debug , stdout , D , E log4j.appender.stdout = org.apache.log4j.ConsoleAppender l ...

  9. 通过css使用background-color为背景图添加遮罩效果

    一个div同时设置background-color和background-image的话,color是处于img层下方的,无法实现遮罩效果,所以需要再创建一个div作为其子div,然后设置子div的背 ...

  10. 双内网渗透代理之reGeorg&plus;Proxifier

    由于这个工具第一次体验感觉还不错,很稳定.因此在这记录一下reGeorg+Proxifier的配置及其使用. 下载地址 :https://github.com/sensepost/reGeorg.gi ...