首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么在后台线程中更新ProgressBar不会抛出CalledFromWrongThreadException

在Android开发中,更新UI组件(如ProgressBar)必须在主线程(也称为UI线程)中进行,否则会抛出CalledFromWrongThreadException异常。这是因为Android采用了单线程模型,即所有与UI相关的操作都必须在主线程中执行,以确保界面的稳定性和一致性。

后台线程通常用于执行耗时的任务,例如网络请求、数据库操作或计算密集型任务。由于这些任务可能会阻塞主线程,因此在后台线程中直接更新UI组件是不安全的。

为了在后台线程中更新ProgressBar而不抛出异常,可以使用以下方法之一:

  1. 使用Handler:可以在后台线程中创建一个Handler对象,并使用post或sendMessage方法将更新UI的任务发送到主线程的消息队列中。主线程接收到消息后,可以在处理消息的回调方法中更新ProgressBar。具体示例代码如下:
代码语言:txt
复制
Handler handler = new Handler(Looper.getMainLooper());

// 在后台线程中执行耗时任务
new Thread(new Runnable() {
    @Override
    public void run() {
        // 执行耗时任务

        // 发送消息到主线程更新ProgressBar
        handler.post(new Runnable() {
            @Override
            public void run() {
                // 更新ProgressBar
            }
        });
    }
}).start();
  1. 使用AsyncTask:AsyncTask是Android提供的一个方便的工具类,用于在后台线程执行任务并在主线程更新UI。AsyncTask封装了线程管理和消息处理的细节,可以简化开发过程。具体示例代码如下:
代码语言:txt
复制
new AsyncTask<Void, Void, Void>() {
    @Override
    protected Void doInBackground(Void... voids) {
        // 执行耗时任务
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        // 在主线程更新ProgressBar
        // 更新ProgressBar
    }
}.execute();

无论使用哪种方法,都需要确保在后台线程中执行耗时任务,并在主线程中更新UI组件,以避免抛出CalledFromWrongThreadException异常。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

关于 Android 进程和线程,你必须了解的东西

进程 ---- 当一个程序第一次启动的时候,Android 会启动一个 Linux 进程和一个主线程。默认情况下,同一应用的所有组件均在相同的进程运行,且大多数应用都不会改变这一点。...不同形式的线程虽然都是线程,但是它们仍然有不同的特性和使用场景。AsyncTask 封装了线程池和 Handler,它主要是为了方便开发者线程更新 UI。...而 Android 规定访问 UI 只能在主线程中进行,如果在子线程访问 UI,那么程序就回抛出异常。...original thread that created a view hierarch can ouch its views."); } } Android 系统为什么不允许线程访问...这是因为 Android 的 UI 控件不是线程安全的,如果在多线程并发访问可能会导致 UI 控件处于不可预期的状态,那为什么系统不对 UI 控件的访问加上锁机制呢?

78020

使用AsyncTask异步更新UI界面及原理分析

概述: AsyncTask是Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类。...AsyncTask抽象出后台线程运行的五个状态,分别是:1、准备运行,2、正在后台运行,3、进度更新,4、完成后台任务,5、取消任务,对于这五个阶段,AsyncTask提供了五个回调函数: 1、准备运行...2、正在后台运行:doInBackground(Params...),该回调函数由后台线程onPreExecute()方法执行结束后立即调用。通常在这里执行耗时的后台计算。...2.Progress,后台计算执行过程,进步单位(progress units)的类型。(就是后台程序已经执行了百分之几了。) 3.Result, 后台执行返回的结果的类型。...AsyncTask,InternalHandler是UI线程上创建的,它接收来自工作线程的消息,实现代码如下: AsyncTask.java 1 private static class InternalHandler

1.3K110

Android多线程-AsyncTaskyi(一)

是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后会把执行的进度和最终结果传递给主线程更新UI。...(3)onProgressUpdate(Progress…),线程执行,该方法publishProgress(Progress… values)方法被调用后执行,一般用于更新UI进度,如更新进度条的当前进度...UI线程,并执行一些UI相关的操作,如更新UI视图。...(5)onCancelled(),线程执行,当异步任务被取消时,该方法将被调用,要注意的是这个时onPostExecute将不会被执行。...(values);; } } AsynTaskActivity实现了更新UI的接口DownLoadAsyncTask.UpdateUI,用于更新线程progressBar的进度,由于使用的测试版本是

60920

AndroidAsyncTask的使用

Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,多个任务同时执行时...执行过程可以调用publishProgress(Progress... values)来更新进度信息。...使用的时候,有几点需要格外注意: 1.异步任务的实例必须在UI线程创建。 2.execute(Params... params)方法必须在UI线程调用。...4.不能在doInBackground(Params... params)更改UI组件的信息。 5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。...textView.setText("loading..." + progresses[0] + "%"); } //onPostExecute方法用于执行完后台任务后更新

43220

安卓开发_浅谈AsyncTask

但是线程无法去操作主线程(UI 线程),线程操作UI线程会出现错误。因此android提供了一个类Handler来线程更新UI线程,用发消息的机制更新UI界面,呈现给用户。...Progress:后台任务执行返回进度值的类型,后台任务执行的百分比   Result:后台执行任务完成后返回结果的类型,比如String,Integer等。...6、onCancelled(),在用户取消线程操作的时候调用。线程调用onCancelled()的时候调用。   几个方法是有规律的。   ...()手动执行,更新任务的进度。...四、几条必须遵守的准则:   使用的时候,有几点需要格外注意:   1.异步任务的实例必须在UI线程创建。

1.6K70

android异步任务asyntask详解

Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,多个任务同时执行时...执行过程可以调用publishProgress(Progress... values)来更新进度信息。...使用的时候,有几点需要格外注意: 1.异步任务的实例必须在UI线程创建。 2.execute(Params... params)方法必须在UI线程调用。...4.不能在doInBackground(Params... params)更改UI组件的信息。 5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。...            textView.setText("loading..." + progresses[0] + "%");           }   //onPostExecute方法用于执行完后台任务后更新

95680

Android 使用AsyncTask实现断点续传

2.onPreExecute(),execute(Params… params)被调用后立即执行,一般用来执行后台任务前对UI做一些标记。   ...执行过程可以调用publishProgress(Progress… values)来更新进度信息。   ...5.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法,直接将结果显示到UI组件上。   ...使用的时候,有几点需要格外注意:   1.异步任务的实例必须在UI线程创建。   2.execute(Params… params)方法必须在UI线程调用。   ...4.不能在doInBackground(Params… params)更改UI组件的信息。   5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。

63540

Android开发高级进阶——多线程(实现简单下载器)

一.什么是多线程? ---- 线程:是进程单一的连续控制流程/执行路径。 多线程:多个线程并行执行。 二.为什么要使用多线程?...---- Android3.0以及以后的版本,禁止线程执行网络请求,否则会抛出异常,可见UI线程执行耗时操作是不推荐的行为。所以,进行与耗时操作同步进行的操作时(即并行)使用多线程。...四.如何使用多线程? ---- 我们经常说Android的主线程线程不安全的,所以只能在主线程更新UI。那么如何更新线程且保证线程是安全的呢?...message发送到主线程,并在handleMessage更新进度条。...()方法通过读文件、写文件完成下载任务,并调用publishProgress()方法发出更新进度,onProgressUpdate()方法执行更新进度,onPostExecute()方法销毁进度条对话框

85320

为什么我的子线程更新了 UI 没报错?借此,纠正一些Android 程序员的一个知识误区

开门见山: 这个误区是:子线程不能更新 UI ,其应该分类讨论,而不是绝对的。...半小时前,我的 XRecyclerView 群里面,一位群友私聊我,问题是: 为什么我的子线程更新了 UI 没报错? 我叫他发下代码我看,如下,十分简单的代码。...onResponse(Response response) throws IOException { title.setText(response.body().string()); // 这里线程更新了...他用了 OkHttp 的异步 enqueue 的请求,并在成功后更新了 textView 的 text。 明确一点: okhttp 的同步异步的回调都是线程里面的。...如果你的子线程更新代码满足下面的条件下,那么它可以顺利运行: 修改应用层的 viewRootImpl.java 源码,解除限制 把你更新代码写在 onResume 之前,例如 onCreate 里面

1.2K70

可能是全网最简单透彻的安卓子线程更新 UI 解析

相信下面的代码大家看过很多遍了, onCreate() 生命周期里开启一个线程更新 UI ,居然没有闪退和异常( 大概率情况下是没有问题的 ) @Override protected...UI"); Log.e("MyButton", "子线程更新UI"); } }).start(); } 我们线程里睡眠一秒试试看...UI"); Log.e("MyButton", "子线程更新UI"); } }).start(); } 很明显,抛出异常闪退...测量 方法里才会对这个值进行赋值,答案也就很明显了,当我们线程里 setText 的时候,其实只是简单的设置了这个控件要显示的值,并不会立即去显示,因为 mLayout 是为空,为什么为空,因为只有...最后扩展一下,如果就是想在子线程更新 UI 怎么办呢,onResume 之前就行,或者把 View 的 ViewRootImpl 实例化放到子线程来进行,这样就不会因为非 UI 线程抛出异常。

1.1K10

Android子线程更新UI问题的深入讲解

前言 Android项目中经常有碰到这样的问题,线程完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法。...UI吗,为什么情形一可以正常运行,情形二不能正常运行呢; 子线程修改UI出现异常,与什么方法有关 首先从出现异常的log日志入手,发现出现异常的方法调用顺序如下: TextView.setText...的线程就是主线程,当前线程不是主线程的时候,就抛出异常。...总结一下: 1.Android更新UI会调用View的requestLayout()方法,requestLayout方法,获取ViewParent,然后调用ViewParent的requestLayout...= Thread.currentThread()判断为true,所以不会抛出只能在主线程更新UI的异常。

1.1K30

Android基础总结(7)——异步消息处理

此外,我们也不要被服务的后台概念所迷惑,实际上服务并不会自动开启线程,所有的代码都是默认运行在主线程。...也就是说,如果想要更新应用程序的UI元素,则必须在主线程中进行,否则就会出现异常。   ...但是有些时候,我们必须利用多线程过去执行一些耗时任务,然后根据任务执行的结果开更新相应的UI控件,那么,Android提供了两种方法来解决UI操作存在的问题: 异步消息处理机制,完美解决了线程中进行...执行过程可以调用publishProgress(Progress... values)来更新进度信息。...使用的时候,有几点需要格外注意: 异步任务的实例必须在UI线程创建。 execute(Params... params)方法必须在UI线程调用。

74450

AsyncTask和Handler对比

UI进度更新),最后反馈执行的结果给UI主线程....使用的优点: l  结构清晰,功能定义明确 l  对于多个后台任务时,简单,清晰 使用的缺点: l  单个后台异步处理时,显得代码过多,结构过于复杂(相对性) AsyncTask介绍 Android的...首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程完成,因此异步处理是不可避免的。...此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。执行过程可以调用publicProgress(Progress…)来更新任务的进度。...方法都会触发onProgressUpdate执行 * onProgressUpdate是UI线程执行,所有可以对UI空间进行操作 */ @Override protected

1.2K50

线程能否操作UI控件

前言 这是一个初级Android工程师面试问题,一般标准答案:子线程不能操作UI控件。 那我为什么还要问这个弱智的问题呢? 因为我心目中的标准答案:子线程不能操作"参与绘制"的UI控件。...= Thread.currentThread()) {//mThread为主线程,也就是UI线程 //子线程抛出异常了 throw new CalledFromWrongThreadException...,如果发现当前的线程Thread.currentThread不等于mThread(主线程/UI线程),也就是子线程。...四、什么是参与绘制 看完上面的内容,肯定有人说答案不就是子线程不能操作UI控件嘛,为什么还要加上"参与绘制"的条件。...View没有ViewParent或者最顶层的ViewParent不是ViewRootImpl,也可以避免调用到ViewRootImpl.invalidateChild-> checkThread,也就不会抛出异常了

74210

Android 多线程:这是一份详细的AsyncTask使用教程

作用 实现多线程 工作线程执行任务,如 耗时任务 异步通信、消息传递 实现工作线程 & 主线程(UI线程)之间的通信,即:将工作线程的执行结果传递给主线程,从而在主线程执行相关的UI操作...必须在UI线程调用 * b. 同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常 * c....实例讲解 下面,我将用1个实例讲解 具体如何使用 `AsyncTask` 6.1 实例说明 点击按钮 则 开启线程执行线程任务 显示后台加载进度 加载完毕后更新UI组件 期间若点击取消按钮...必须在UI线程调用 * b. 同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常 * c....UI操作 使用建议 Activity恢复时的对应方法 重启 任务线程 ---- 8.

1.2K30

Android多线程:AsyncTask使用教程(含实例讲解)

作用 实现多线程 工作线程执行任务,如 耗时任务 异步通信、消息传递 实现工作线程 & 主线程(UI线程)之间的通信,即:将工作线程的执行结果传递给主线程,从而在主线程执行相关的UI操作 从而保证线程安全...必须在UI线程调用 * b. 同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常 * c....实例讲解 下面,我将用1个实例讲解 具体如何使用 AsyncTask 6.1 实例说明 点击按钮 则 开启线程执行线程任务 显示后台加载进度 加载完毕后更新UI组件 期间若点击取消按钮,则取消加载 如下图...MyTask mTask; // 主布局的UI组件 Button button,cancel; // 加载、取消按钮 TextView text; // 更新的UI...必须在UI线程调用 * b. 同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常 * c.

67920

笔记16 | 解析和练习AsyncTask

前言 本节给大家带来的是Android给我们提供的一个轻量级的用于处理异步任务的类:AsyncTask,我们一般是 继承AsyncTask,然后实现异步操作,然后将异步执行的进度,反馈给UI主线程...;还是上面那个后台下载的例子,后台下载, 我们执行下载功能后,我们就无需去关心它的下载过程,当下载完毕后通知我们就可以了~ 3) Android为很么要引入异步任务 因为Android程序刚启动时,会同时启动一个对应的主线程...假如我们非UI线程,比如在主线程new Thread()另外开辟一个线程,然后直接在里面修改UI控件的值; 此时会抛出下述异常: android.view.ViewRoot$CalledFromWrongThreadException...的AsyncTask,我们可以自己开辟一个线程,完成相关操作后,通过下述两种方法进行UI更新: 前面我们学的Handler,我们Handler里写好UI更新,然后通过sendMessage()等的方法通知...UI 更新,另外别忘了Handler写在主线程和子线程的区别哦~ 利用Activity.runOnUiThread(Runnable)把更新ui的代码创建在Runnable,更新UI时,把Runnable

55660

Android进度条ProgressBar的实现代码

ProgressBar进度条 当一个应用在后台执行时,前台界面不会有任何信息,这时,用户根本不知道程序是否执行以及执行的进度等, 因此需要使用进度条来提示程序执行的进度。...//声明一个用于处理消息的Handler类的对象 private Handler mHandler; /** * 主活动onCreate方法,首先获得水平进度条和圆形进度条..., * 然后通过匿名内部类实例化处理消息的Handler类的对象,并重写其handlerMessage方法, * 实现当好吃操作没有完成时更新进度,否则设置进度条不显示。...(Message msg) { if (msg.what == 0x111) { horizonP.setProgress(mProcessStatus);//更新进度...e.printStackTrace(); } return mProcessStatus;//返回新的进度 } }).start();//开启一个新的线程

99031
领券