java子线程切换到主线程_Android子线程切换到UI线程方法总结
线程切换
通过消息发送(发布)和接收(订阅)的方式切换的。
1 .Handler
子线程(非UI线程)调用handler对象sendMessage(msg)方法,将消息发送给关联Looper,Looper将消息存储在MessageQueue消息队列里面。
然后轮巡取出MessageQueue中的消息给UI线程中handler处理,handler得到消息调用handleMessage方法处理消息,从而可以更新Ui。
private Handler handler2=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 1:
//UI线程
textView.setText(msg.obj.toString());
}
}
};
//开启线程执行耗时操作
new Thread(){
@Override
public void run() {
//执行相关耗时操作等等...
//休眠3s
sleep(3000);
Message message = new Message();
//区分标志
message.what=1;
//传参到ui线程
message.obj=123123;
handler2.sendMessage(message);
}
}.start();
复制代码
** 扩展注意:**
1 . Handler机制与Activity生命周期不一致的原因,容易导致内存泄漏。
2 . 实例化 handler
//实例化handler在其他线程的时候要下面这样写(UI线程内部已经实现,无需写)
private Handler handler = new Handler(Looper.getMainLooper());
复制代码
2. Activity.runOnUiThread
用Activity对象的runOnUiThread方法更新,在子线程中通过runOnUiThread()方法更新UI
new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText("#" + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
复制代码
3. View.post(Runnable r)
View.post(Runnableaction),View获得当前线程(即UI线程)的Handler,然后将action对象post到Handler里。
在Handler里,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。
在Handler再次处理该Message时,直接调用runnable的run方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI。
new Thread(){
@Override
public void run() {
super.run();
for (int i=0;i<3;i++){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
tv.post(new Runnable() {
@Override
public void run() {
tv.setText("通过View.post(Runnable r) 方法");
}
});
}
}.run();
复制代码
扩展注意:
子线程能不能更新UI,答案是肯定的。具体阅读下这篇文章:Android 子线程更新UI?
上面就是为了实现用一个Thread来更新tv,可以实现这个功能,刷新UI界面。但是这样是不对的,因为它违背了单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。
4. AsyncTask
内部就是一个Handler和线程池的封装。在线程池中执行后台任务,并在执行过程中将执行进度传递给主线程,当任务执行完毕后,将最终结果传递给主线程。
private class MyAsyncTask extends AsyncTask{
//第一阶段————准备阶段
@Override
protected void onPreExecute() {
super.onPreExecute();
}
//第二阶段————耗时操作
@Override
protected Object doInBackground(Object[] objects) {
for (int i=0;i<3;i++){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return objects[0].toString();
}
//第三阶段———— 更新UI
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
tv.setText(o.toString());
}
}
复制代码
5. Rxjava
RXJAVA的实现,是一种扩展式的观察者模式。
RXJAVA中有四种概念。observable(被观察者),observer(观察者),subscribe(订阅),事件。
Observable和Observer通过subscribe来实现订阅关系。
与传统的观察者模式不同,除了onNext事件外,rxjava还提供了onCompleted和onError。当不再有onNext事件发送时,将以onCompleted事件作为结束。当处理过程中出现异常时,会触发onError,同时队列自动终止,不允许再有事件发出。onCompleted和onError在一个序列中有且只有一个,二者互斥,只能出现一个。
public static void doTask(final Task task) {
//创建被观察者 Observable,它决定什么时候触发事件以及触发怎样的事件。
Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super T> subscriber) {
// 线程执行耗时操作
// task.doOnIOThread();
// subscriber.onNext(task.getT());
subscriber.onCompleted();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
//订阅
.subscribe(new Action1() {
@Override
public void call(T t) {
//主线程更新UI
// task.doOnUIThread();
}
}, new Action1() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
});
}
复制代码
java子线程切换到主线程_Android子线程切换到UI线程方法总结相关推荐
- java 安卓 html文件怎么打开方式_android 浏览器 打开本地html文件的方法
android 浏览器 打开本地html文件的方法有些html文件放在本地磁盘和sdcard,如何用打开这个网页呢? 这种应用在测试时非常有用. 有2个方法: 1. 使用文件管理器 如ES等,需要幸运 ...
- Android ActivityThread(主线程或UI线程)简介
1. ActivityThread功能 它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client ...
- Android异步机制一:使用Thread+Handler实现非UI线程更新UI界面
概述:每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),主线程负责处理和ui相关的事件,因此主线程通常又叫UI线程.而由于Andr ...
- Android开发之UI线程和非UI线程
这里又是老生畅谈的话了,前边已经有多篇文章针对线程进行探究解释,Android开发过程中线程的体现更是淋漓尽致.Android开发过程中涉及到的线程从大类上分可以归为两类:UI线程和非UI线程.本篇就 ...
- 同步上下文(SynchronizationContext) 和 C#中跨线程更新UI的方法总结
同步上下文(SynchronizationContext) 和 C#中跨线程更新UI的方法总结 在C#编程环境中,不允许在工作线程中直接对主线程(UI线程)中的控件进行更新操作.因此,稍微复杂一点的程 ...
- UI线程和Windows消息队列
在Windows应用程序中,窗体是由一种称为"UI线程(User Interface Thread)"的特殊类型的线程创建的. 首先,UI线程是一种"线程",所 ...
- MFC 基础知识:主对话框与子对话框(一)
(仅供使用VS MFC初学者学习,高手莫见笑) 在MFC中通常会使用点击一个按钮,弹出一个子对话框的基础知识,这些都是学习MFC的基础知识,也是非常重要的知识,这里我就简单的讲讲这些知识. 一. 设置 ...
- Android中后台线程如何与UI线程交互
我想关于这个话题已经有很多前辈讨论过了.今天算是一次学习总结吧. 在android的设计思想中,为了确保用户顺滑的操作体验.一些耗时的任务不能够在UI线程中运行,像访问网络就属于这类任务.因此我们必须 ...
- Tkinter 实现弹出子窗口并冻结主窗口
简介 用Tkinter实现自动弹出子窗口并冻结主窗口,子窗口设置按钮,可以解除或者冻结主窗口,效果如下: 代码 import sys import tkinter from tkinter impor ...
最新文章
- 用netty实现zcool_Netty 如何玩转内存使用
- sku属性组合小例子
- AndroidStudio跑起来第一个App时新手遇到的那些坑
- java中的序列化和反序列化
- Canvas Clock
- DeFi巨鲸0xb1向DeBank打赏5 ETH
- java println和print_java中的print和println有区别吗
- 学习C++开发技术,常见误解有哪些?
- 阿里云 网站https设置 sll申请与nginx跳转配置
- 计算机硬盘分区知识简介、Linux企业级分区方案建议
- 基于单片机烟雾温湿度甲醛监测设计
- 福州发布《关于运用大数据加强对市场主体服务和监管实施方案》
- go1.15版本 mod 报An existing connection was forcibly closed by the remote host错误处理
- 2022程序员必备网站
- Birdman Quotes
- Android使用Bugly实现静默安装/自动安装app
- 案例分享:Qt + 树莓派3B+ 智能笔筒系统
- IDEA 添加类注释、方法注释(快捷键 /** + Enter)
- Python中文转数字
- Java高级开发必备--Docker进阶(一篇详细教程,进阶Docker)
热门文章
- 链表的应用 —— 多项式运算(加法+乘法)
- 机器学习基础(七)——sigmoid 函数的性质
- C++基础——非类型模板参数
- 群辉服务器根目录新建文件夹,群晖 synology NAS 存储创建存储空间的方法
- 螺杆泵matlab,基于Matlab与VC++混合编程的螺杆泵转子型线设计
- python从入门到精通pdf清华大学出版社-python从入门到精通 清华大学出版社
- php和python-PHP与Python语言有哪些区别之处?选择哪一个好?
- python自动化办公演示视频-2020年最新Python自动化办公视频教程(2020/9/3)
- python趣味编程100例-Python趣味编程与精彩实例,码高少儿编程 编
- python编程100例-Python3经典100例(①)