当前位置:首页 » 安卓系统 » android的ui线程

android的ui线程

发布时间: 2022-11-12 15:03:26

Ⅰ Android主线程到底是什么

  • Android中关于主线程的理解:

Android的主线程是UI线程,在Android中,四大组件运行在主线程中,在主线程中做耗时操作会导致程序出现卡顿甚至出现ANR异常,一个基本常识就是将耗时操作放到子线程中去处理,然后通过Handler回调到主线程。

  • 有三点还需要注意:

  1. 因为四大组件运行在一个主线程中,那么若果当前界面在显示的时候,后台的activity仍有处理逻辑再运行的话,仍然会造成当前界面的卡顿。

  2. 通过Handler回调到主线程只是避免程序出现ANR的第一步,必须要注意handler中逻辑处理的耗时,如果将很多消息都扔给了handler,那么也会给主线程造成压力,导致程序运行卡顿。

  3. 四大组件、Handler都是在一个线程中,那么主线程在同一时刻不可能发送两个广播,换句话说就是若果能够保证所有的广播都是在主线程中发送,那么广播内部其实不需要加上对异步操作的处理。

Ⅱ 在android中!什么叫ui线程!和主线程的区别是什么

UI线程就是主线程 你在更新UI时必须要在主线程中更新 所以说也叫UI线程

Ⅲ android开发非UI线程和UI线程区别详解,请回答专业知识谢谢。

UI线程,即主线程,在主线程里不能进行耗时的操作,不然系统会弹出ANR提示框,所以一般的耗时操作都是放到非UI线程里去完成,即子线程。目前在开发层面的区别应该主要是这个吧,其它的暂时没听说。

Ⅳ Android的主线程是UI线程吗

是的,只是叫法上的不同。因为Android处于安全性考虑,只允许在主线程中操作UI,所以也叫UI线程。

Ⅳ Android开发中多线程与UI更新

直接在UI线程中开启子线程来更新TextView显示的内容,运行程序我们会发现,如下错误:android.view.ViewRoot$: Only the original thread that created a view hierarchy can touch its views.翻译过来就是:只有创建这个控件的线程才能去更新该控件的内容。

所有的UI线程要去负责View的创建并且维护它,例如更新冒个TextView的显示,都必须在主线程中去做,我们不能直接在UI线程中去创建子线程,要利用消息机制:handler,如下就是handler的简单工作原理图:

既然android给我们提供了Handler机制来解决这样的问题,请看如下代码:

public class HandlerTestActivity extends Activity { private TextView tv; private static final int UPDATE = 0; private Handler handler = new Handler() { @Overridepublic void handleMessage(Message msg) { // TODO 接收消息并且去更新UI线程上的控件内容if (msg.what == UPDATE) { // Bundle b = msg.getData();// tv.setText(b.getString("num")); tv.setText(String.valueOf(msg.obj)); } super.handleMessage(msg); } }; /** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv = (TextView) findViewById(R.id.tv); new Thread() { @Overridepublic void run() { // TODO 子线程中通过handler发送消息给handler接收,由handler去更新TextView的值try { for (int i = 0; i < 100; i++) { Thread.sleep(500); Message msg = new Message(); msg.what = UPDATE; // Bundle b = new Bundle();// b.putString("num", "更新后的值:" + i);// msg.setData(b); msg.obj = "更新后的值:" + i; handler.sendMessage(msg); } } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); }}

我们就通过Handler机制来处理了子线程去更新UI线程控件问题,Andrid开发中要经常用到这种机制。

Ⅵ android 为什么要设计ui线程

UI线程,即主线程。为何将UI线程和其他事物线程,是由于其他事务处理会需要更多的时间去加载,也就是所谓的耗时操作,这样不会导致页面加载需要很久(至少画面出来了,数据可以略慢)。设计UI线程是为了使得程序能够独立完成界面加载不受其他线程影响速度。

Ⅶ android怎么让代码在UI线程运行

稍微有过Andorid开发经验的同学都知道,Android开发中涉及到UI变动的操作,必须在主线程中执行, 否则会crash
这就需要我们将代码抛到主线程执行。
第一种方式,是通过Activity.runOnUiThread()来做。这不是一个好方法,毕竟Activity这种东西,在子线程中可遇不可求。也千万不要因此而将Activity传来传去,甚至对Context进行强转,那样太过难看。
那么,只剩下通过Handler手动将代码抛到主线程了。这就需要,Handler具有主线程的Looper对象。具体的原因可以参考我之前的博客:【Android】结合源码解析Android消息队列工作流程 。
两种实现方式:
1. 在主线程中创建Handler
2. 直接通过MainLooper,构造handler
http://blog.csdn.net/u013015161/article/details/52760207

Ⅷ Android 中的“子线程”解析

Android 中线程可分为 主线程 和 子线程 两类,其中主线程也就是 UI线程 ,它的主要这作用就是运行四大组件、处理界面交互。子线程则主要是处理耗时任务,也是我们要重点分析的。

首先 Java 中的各种线程在 Android 里是通用的,Android 特有的线程形态也是基于 Java 的实现的,所以有必要先简单的了解下 Java 中的线程,本文主要包括以下内容:

在 Java 中要创建子线程可以直接继承 Thread 类,重写 run() 方法:

或者实现 Runnable 接口,然后用Thread执行Runnable,这种方式比较常用:

简单的总结下:

Callable 和 Runnable 类似,都可以用来处理具体的耗时任务逻辑的,但是但具体的差别在哪里呢?看一个小例子:

定义 MyCallable 实现了 Callable 接口,和之前 Runnable 的 run() 方法对比下, call() 方法是有返回值的哦,泛型就是返回值的类型:

一般会通过线程池来执行 Callable (线程池相关内容后边会讲到),执行结果就是一个 Future 对象:

可以看到,通过线程池执行 MyCallable 对象返回了一个 Future 对象,取出执行结果。

Future 是一个接口,从其内部的方法可以看出它提供了取消任务(有坑!!!)、判断任务是否完成、获取任务结果的功能:

Future 接口有一个 FutureTask 实现类,同时 FutureTask 也实现了 Runnable 接口,并提供了两个构造函数:

用 FutureTask 一个参数的构造函数来改造下上边的例子:

FutureTask 内部有一个 done() 方法,代表 Callable 中的任务已经结束,可以用来获取执行结果:

所以 Future + Callable 的组合可以更方便的获取子线程任务的执行结果,更好的控制任务的执行,主要的用法先说这么多了,其实 AsyncTask 内部也是类似的实现!

注意, Future 并不能取消掉运行中的任务,这点在后边的 AsyncTask 解析中有提到。

Java 中线程池的具体的实现类是 ThreadPoolExecutor ,继承了 Executor 接口,这些线程池在 Android 中也是通用的。使用线程池的好处:

常用的构造函数如下:

一个常规线程池可以按照如下方式来实现:

执行任务:

基于 ThreadPoolExecutor ,系统扩展了几类具有新特性的线程池:

线程池可以通过 execute() 、 submit() 方法开始执行任务,主要差别从方法的声明就可以看出,由于 submit() 有返回值,可以方便得到任务的执行结果:

要关闭线程池可以使用如下方法:

IntentService 是 Android 中一种特殊的 Service,可用于执行后台耗时任务,任务结束时会自动停止,由于属于系统的四大组件之一,相比一般线程具有较高的优先级,不容易被杀死。用法和普通 Service 基本一致,只需要在 onHandleIntent() 中处理耗时任务即可:

至于 HandlerThread,它是 IntentService 内部实现的重要部分,细节内容会在 IntentService 源码中说到。

IntentService 首次创建被启动的时候其生命周期方法 onCreate() 会先被调用,所以我们从这个方法开始分析:

这里出现了 HandlerThread 和 ServiceHandler 两个类,先搞明白它们的作用,以便后续的分析。

首先看 HandlerThread 的核心实现:

首先它继承了 Thread 类,可以当做子线程来使用,并在 run() 方法中创建了一个消息循环系统、开启消息循环。

ServiceHandler 是 IntentService 的内部类,继承了 Handler,具体内容后续分析:

现在回过头来看 onCreate() 方法主要是一些初始化的操作, 首先创建了一个 thread 对象,并启动线程,然后用其内部的 Looper 对象 创建一个 mServiceHandler 对象,将子线程的 Looper 和 ServiceHandler 建立了绑定关系,这样就可以使用 mServiceHandler 将消息发送到子线程去处理了。

生命周期方法 onStartCommand() 方法会在 IntentService 每次被启动时调用,一般会这里处理启动 IntentService 传递 Intent 解析携带的数据:

又调用了 start() 方法:

就是用 mServiceHandler 发送了一条包含 startId 和 intent 的消息,消息的发送还是在主线程进行的,接下来消息的接收、处理就是在子线程进行的:

当接收到消息时,通过 onHandleIntent() 方法在子线程处理 intent 对象, onHandleIntent() 方法执行结束后,通过 stopSelf(msg.arg1) 等待所有消息处理完毕后终止服务。

为什么消息的处理是在子线程呢?这里涉及到 Handler 的内部消息机制,简单的说,因为 ServiceHandler 使用的 Looper 对象就是在 HandlerThread 这个子线程类里创建的,并通过 Looper.loop() 开启消息循环,不断从消息队列(单链表)中取出消息,并执行,截取 loop() 的部分源码:

dispatchMessage() 方法间接会调用 handleMessage() 方法,所以最终 onHandleIntent() 就在子线程中划线执行了,即 HandlerThread 的 run() 方法。

这就是 IntentService 实现的核心,通过 HandlerThread + Hanlder 把启动 IntentService 的 Intent 从主线程切换到子线程,实现让 Service 可以处理耗时任务的功能!

AsyncTask 是 Android 中轻量级的异步任务抽象类,它的内部主要由线程池以及 Handler 实现,在线程池中执行耗时任务并把结果通过 Handler 机制中转到主线程以实现UI操作。典型的用法如下:

从 Android3.0 开始,AsyncTask 默认是串行执行的:

如果需要并行执行可以这么做:

AsyncTask 的源码不多,还是比较容易理解的。根据上边的用法,可以从 execute() 方法开始我们的分析:

看到 @MainThread 注解了吗?所以 execute() 方法需要在主线程执行哦!

进而又调用了 executeOnExecutor() :

可以看到,当任务正在执行或者已经完成,如果又被执行会抛出异常!回调方法 onPreExecute() 最先被执行了。

传入的 sDefaultExecutor 参数,是一个自定义的串行线程池对象,所有任务在该线程池中排队执行:

可以看到 SerialExecutor 线程池仅用于任务的排队, THREAD_POOL_EXECUTOR 线程池才是用于执行真正的任务,就是我们线程池部分讲到的 ThreadPoolExecutor :

再回到 executeOnExecutor() 方法中,那么 exec.execute(mFuture) 就是触发线程池开始执行任务的操作了。

那 executeOnExecutor() 方法中的 mWorker 是什么? mFuture 是什么?答案在 AsyncTask 的构造函数中:

原来 mWorker 是一个 Callable 对象, mFuture 是一个 FutureTask 对象,继承了 Runnable 接口。所以 mWorker 的 call() 方法会在 mFuture 的 run() 方法中执行,所以 mWorker 的 call() 方法在线程池得到执行!

同时 doInBackground() 方法就在 call() 中方法,所以我们自定义的耗时任务逻辑得到执行,不就是我们第二部分讲的那一套吗!

doInBackground() 的返回值会传递给 postResult() 方法:

就是通过 Handler 将最终的耗时任务结果从子线程发送到主线程,具体的过程是这样的, getHandler() 得到的就是 AsyncTask 构造函数中初始化的 mHandler , mHander 又是通过 getMainHandler() 赋值的:

可以在看到 sHandler 是一个 InternalHandler 类对象:

所以 getHandler() 就是在得到在主线程创建的 InternalHandler 对象,所以
就可以完成耗时任务结果从子线程到主线程的切换,进而可以进行相关UI操作了。
当消息是 MESSAGE_POST_RESULT 时,代表任务执行完成, finish() 方法被调用:

如果任务没有被取消的话执行 onPostExecute() ,否则执行 onCancelled() 。

如果消息是 MESSAGE_POST_PROGRESS , onProgressUpdate() 方法被执行,根据之前的用法可以 onProgressUpdate() 的执行需要我们手动调用 publishProgress() 方法,就是通过 Handler 来发送进度数据:

进行中的任务如何取消呢?AsyncTask 提供了一个 cancel(boolean mayInterruptIfRunning) ,参数代表是否中断正在执行的线程任务,但是呢并不靠谱, cancel() 的方法注释中有这么一段:

大致意思就是调用 cancel() 方法后, onCancelled(Object) 回调方法会在 doInBackground() 之后被执行而 onPostExecute() 将不会被执行,同时你应该 doInBackground() 回调方法中通过 isCancelled() 来检查任务是否已取消,进而去终止任务的执行!

所以只能自己动手了:

AsyncTask 整体的实现流程就这些了,源码是最好的老师,自己跟着源码走一遍有些问题可能就豁然开朗了!

Ⅸ android ui线程何时销毁

一个App只允许一个UI线程实例的存在,当此APP退出的时候才会销毁。或者内存不够的时候,才可以销毁,用户在APP控制中,也可以手动销毁。

热点内容
仓单加密 发布:2025-03-04 15:54:45 浏览:899
java架构师面试 发布:2025-03-04 15:54:05 浏览:968
安卓手机如何取饿了么会员 发布:2025-03-04 15:53:28 浏览:185
c语言int和double 发布:2025-03-04 15:38:04 浏览:443
手游编程入门 发布:2025-03-04 15:30:55 浏览:899
android进程被杀 发布:2025-03-04 15:30:52 浏览:394
火车的无线密码都是什么 发布:2025-03-04 15:08:42 浏览:455
存单锁住后如何重置密码 发布:2025-03-04 15:08:17 浏览:569
sqlintchar 发布:2025-03-04 14:55:21 浏览:483
切水泥解压 发布:2025-03-04 14:41:55 浏览:501