线程切换

通过消息发送(发布)和接收(订阅)的方式切换的。

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线程方法总结相关推荐

  1. java 安卓 html文件怎么打开方式_android 浏览器 打开本地html文件的方法

    android 浏览器 打开本地html文件的方法有些html文件放在本地磁盘和sdcard,如何用打开这个网页呢? 这种应用在测试时非常有用. 有2个方法: 1. 使用文件管理器 如ES等,需要幸运 ...

  2. Android ActivityThread(主线程或UI线程)简介

    1. ActivityThread功能 它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client ...

  3. Android异步机制一:使用Thread+Handler实现非UI线程更新UI界面

    概述:每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),主线程负责处理和ui相关的事件,因此主线程通常又叫UI线程.而由于Andr ...

  4. Android开发之UI线程和非UI线程

    这里又是老生畅谈的话了,前边已经有多篇文章针对线程进行探究解释,Android开发过程中线程的体现更是淋漓尽致.Android开发过程中涉及到的线程从大类上分可以归为两类:UI线程和非UI线程.本篇就 ...

  5. 同步上下文(SynchronizationContext) 和 C#中跨线程更新UI的方法总结

    同步上下文(SynchronizationContext) 和 C#中跨线程更新UI的方法总结 在C#编程环境中,不允许在工作线程中直接对主线程(UI线程)中的控件进行更新操作.因此,稍微复杂一点的程 ...

  6. UI线程和Windows消息队列

    在Windows应用程序中,窗体是由一种称为"UI线程(User Interface Thread)"的特殊类型的线程创建的. 首先,UI线程是一种"线程",所 ...

  7. MFC 基础知识:主对话框与子对话框(一)

    (仅供使用VS MFC初学者学习,高手莫见笑) 在MFC中通常会使用点击一个按钮,弹出一个子对话框的基础知识,这些都是学习MFC的基础知识,也是非常重要的知识,这里我就简单的讲讲这些知识. 一. 设置 ...

  8. Android中后台线程如何与UI线程交互

    我想关于这个话题已经有很多前辈讨论过了.今天算是一次学习总结吧. 在android的设计思想中,为了确保用户顺滑的操作体验.一些耗时的任务不能够在UI线程中运行,像访问网络就属于这类任务.因此我们必须 ...

  9. Tkinter 实现弹出子窗口并冻结主窗口

    简介 用Tkinter实现自动弹出子窗口并冻结主窗口,子窗口设置按钮,可以解除或者冻结主窗口,效果如下: 代码 import sys import tkinter from tkinter impor ...

最新文章

  1. 用netty实现zcool_Netty 如何玩转内存使用
  2. sku属性组合小例子
  3. AndroidStudio跑起来第一个App时新手遇到的那些坑
  4. java中的序列化和反序列化
  5. Canvas Clock
  6. DeFi巨鲸0xb1向DeBank打赏5 ETH
  7. java println和print_java中的print和println有区别吗
  8. 学习C++开发技术,常见误解有哪些?
  9. 阿里云 网站https设置 sll申请与nginx跳转配置
  10. 计算机硬盘分区知识简介、Linux企业级分区方案建议
  11. 基于单片机烟雾温湿度甲醛监测设计
  12. 福州发布《关于运用大数据加强对市场主体服务和监管实施方案》
  13. go1.15版本 mod 报An existing connection was forcibly closed by the remote host错误处理
  14. 2022程序员必备网站
  15. Birdman Quotes
  16. Android使用Bugly实现静默安装/自动安装app
  17. 案例分享:Qt + 树莓派3B+ 智能笔筒系统
  18. IDEA 添加类注释、方法注释(快捷键 /** + Enter)
  19. Python中文转数字
  20. Java高级开发必备--Docker进阶(一篇详细教程,进阶Docker)

热门文章

  1. 链表的应用 —— 多项式运算(加法+乘法)
  2. 机器学习基础(七)——sigmoid 函数的性质
  3. C++基础——非类型模板参数
  4. 群辉服务器根目录新建文件夹,群晖 synology NAS 存储创建存储空间的方法
  5. 螺杆泵matlab,基于Matlab与VC++混合编程的螺杆泵转子型线设计
  6. python从入门到精通pdf清华大学出版社-python从入门到精通 清华大学出版社
  7. php和python-PHP与Python语言有哪些区别之处?选择哪一个好?
  8. python自动化办公演示视频-2020年最新Python自动化办公视频教程(2020/9/3)
  9. python趣味编程100例-Python趣味编程与精彩实例,码高少儿编程 编
  10. python编程100例-Python3经典100例(①)