Android--线程--AsyncTask

本文介绍了Android中的线程概念及重要性,特别是在保持UI流畅性方面的作用。深入探讨了主线程(UI线程)的功能及其限制,以及如何使用AsyncTask类在后台线程执行耗时任务的同时更新UI。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.线程

线程,是程序执行流的最小单元。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。而在单个程序中同时运行多个线程完成不同的工作,称为多线程。

2.Android线程

应用启动时,系统会为应用创建一个名为“主线程”的执行线程。此线程非常重要,因为它负责将事件分派给相应的用户界面小部件,其中包括绘图事件。此外,它也是应用与Android UI 工具包组件(来自 android.widgetandroid.view 软件包的组件)进行交互的线程。因此,主线程有时也称为UI 线程。

系统不会为每个组件实例创建单独的线程。运行于同一进程的所有组件均在 UI 线程中实例化,并且对每个组件的系统调用均由该线程进行分派。因此,响应系统回调的方法(例如,报告用户操作的onKeyDown()或生命周期回调方法)始终在进程的 UI 线程中运行。

例如,当用户触摸屏幕上的按钮时,应用的 UI 线程会将触摸事件分派给小部件,而小部件反过来又设置其按下状态,并将失效请求发布到事件队列中。UI 线程从队列中取消该请求并通知小部件应该重绘自身。

在应用执行繁重的任务以响应用户交互时,除非正确实现应用,否则这种单线程模式可能会导致性能低下。具体地讲,如果 UI 线程需要处理所有任务,则执行耗时很长的操作(例如,网络访问或数据库查询)将会阻塞整个 UI。一旦线程被阻塞,将无法分派任何事件,包括绘图事件。从用户的角度来看,应用显示为挂起。更糟糕的是,如果 UI线程被阻塞超过几秒钟时间(目前大约是 5 秒钟),用户就会看到一个让人厌烦的“应用无响应”(ANR)对话框。如果引起用户不满,他们可能就会决定退出并卸载此应用。

此外,Android UI 工具包并非线程安全工具包。因此,您不得通过工作线程操纵 UI,而只能通过 UI 线程操纵用户界面。因此,Android 的单线程模式必须遵守两条规则:

1.不要阻塞 UI 线程

2.不要在 UI 线程之外访问 Android UI 工具包

根据上述单线程模式,要保证应用 UI 的响应能力,关键是不能阻塞 UI 线程。如果执行的操作不能很快完成,则应确保它们在单独的线程(“后台”或“工作”线程)中运行。线程是程序员进阶的一道重要门槛。对于移动开发者来说,“将耗时的任务放到子线程去执行,以保证UI线程的流畅性”是线程编程的第一金科玉律。要通过工作线程处理更复杂的交互,可以考虑在工作线程中使用Handler处理来自 UI 线程的消息。当然,最好的解决方案或许是扩展 AsyncTask 类,Android提供的该类简化了与UI 进行交互所需执行的工作线程任务。

3.Android--AsyncTask

AsyncTask
public abstract class AsyncTask
extends Object
java.lang.Object
↳ android.os.AsyncTask<Params, Progress, Result>

AsyncTask是android提供的轻量级的异步类,可以直接继承AsyncTask在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程。使用起来简便快捷,过程可控。

AsyncTask定义的三种泛型类型 Params,Progress和Result:

1.Params 启动任务执行的输入参数,比如HTTP请求的URL。

2.Progress 后台任务执行的百分比。

3.Result 后台执行任务最终返回的结果,比如String。

使用过AsyncTask必须重写doInBackground(Params…)方法:

doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。

有必要的话还得重写其他方法,但不是必须的:

onPostExecute(Result)  相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回

onProgressUpdate(Progress…)   可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。

onPreExecute(Result)        这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。

onCancelled()             用户调用取消时,要做的操作

其中执行顺序为:onPreExecute(),doInBackground(Params...), onProgressUpdate(Progress...), onPostExecute(Result)

使用AsyncTask类,尽管方便快捷,但也有很多限制:

1.Task的实例必须在UI thread中创建;

2.execute方法必须在UI thread中调用;

3.不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这些方法;

4.AsyncTask只能被执行一次,多次调用时将会出现异常;

4.Code

如下图,当在UI线程中使用URI连接下载数据显示时将会出现错误:



使用AsyncTask类改进如下:

    public class UriTestTask extends AsyncTask<URL, Void, String> {
        @Override
        protected String doInBackground(URL... urls) {
            URL searchUrl = urls[0];
            String SearchResults = null;
            try {
                SearchResults = NetworkUtils.getResponseFromHttpUrl(searchUrl);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return SearchResults;
        }

        @Override
        protected void onPostExecute(String s) {
            if (s != null && !s.equals("")) {
                mSearchResultsTextView.setText(s);
            }
        }
    }
并在UI线程中启动如下:

@Override

public boolean onOptionsItemSelected(MenuItem item) { int itemThatWasClickedId = item.getItemId(); if (itemThatWasClickedId == R.id.action_search) { makeSearchQuery(); return true; } return super.onOptionsItemSelected(item); } private void makeSearchQuery() { String queryStr = mSearchBoxEditText.getText().toString(); URL searchUrl = NetworkUtils.buildUrl(queryStr); mUrlDisplayTextView.setText(searchUrl.toString()); new UriTestTask().execute(searchUrl); }
App运行正常如下图:


5.参考

AsyncTask:https://developer.android.com/reference/android/os/AsyncTask.html

进程与线程:https://developer.android.com/guide/components/processes-and-threads.html


内容概要:本文介绍了多种开发者工具及其对开发效率的提升作用。首先,介绍了两款集成开发环境(IDE):IntelliJ IDEA 以其智能代码补全、强大的调试工具和项目管理功能适用于Java开发者;VS Code 则凭借轻量级和多种编程语言的插件支持成为前端开发者的常用工具。其次,提到了基于 GPT-4 的智能代码生成工具 Cursor,它通过对话式编程显著提高了开发效率。接着,阐述了版本控制系统 Git 的重要性,包括记录代码修改、分支管理和协作功能。然后,介绍了 Postman 作为 API 全生命周期管理工具,可创建、测试和文档化 API,缩短前后端联调时间。再者,提到 SonarQube 这款代码质量管理工具,能自动扫描代码并检测潜在的质量问题。还介绍了 Docker 容器化工具,通过定义应用的运行环境和依赖,确保环境一致性。最后,提及了线上诊断工具 Arthas 和性能调优工具 JProfiler,分别用于生产环境排障和性能优化。 适合人群:所有希望提高开发效率的程序员,尤其是有一定开发经验的软件工程师和技术团队。 使用场景及目标:①选择合适的 IDE 提升编码速度和代码质量;②利用 AI 编程助手加快开发进程;③通过 Git 实现高效的版本控制和团队协作;④使用 Postman 管理 API 的全生命周期;⑤借助 SonarQube 提高代码质量;⑥采用 Docker 实现环境一致性;⑦运用 Arthas 和 JProfiler 进行线上诊断和性能调优。 阅读建议:根据个人或团队的需求选择适合的工具,深入理解每种工具的功能特点,并在实际开发中不断实践和优化。
内容概要:本文围绕低轨(LEO)卫星通信系统的星间切换策略展开研究,针对现有研究忽略终端运动影响导致切换失败率高的问题,提出了两种改进策略。第一种是基于预测的多属性无偏好切换策略,通过预测终端位置建立切换有向图,并利用NPGA算法综合服务时长、通信仰角和空闲信道数优化切换路径。第二种是多业务切换策略,根据不同业务需求使用层次分析法设置属性权重,并采用遗传算法筛选切换路径,同时引入多业务切换管理方法保障实时业务。仿真结果显示,这两种策略能有效降低切换失败率和新呼叫阻塞率,均衡卫星负载。 适合人群:从事卫星通信系统研究的科研人员、通信工程领域的研究生及工程师。 使用场景及目标:①研究和优化低轨卫星通信系统中的星间切换策略;②提高卫星通信系统的可靠性和效率;③保障不同类型业务的服务质量(QoS),特别是实时业务的需求。 其他说明:文章不仅详细介绍了两种策略的具体实现方法,还提供了Python代码示例,包括终端位置预测、有向图构建、多目标优化算法以及业务感知的资源分配等关键环节。此外,还设计了完整的仿真测试框架,用于验证所提策略的有效性,并提供了自动化验证脚本和创新点技术验证方案。部署建议方面,推荐使用Docker容器化仿真环境、Redis缓存卫星位置数据、GPU加速遗传算法运算等措施,以提升系统的实时性和计算效率。
内容概要:该论文深入研究了光纤陀螺(FOG)的温度特性及其补偿方法。首先分析了光纤陀螺各主要光学和电子器件的温度特性,通过有限元方法模拟温度场对陀螺的影响,进行了稳态和瞬态热分析。接着提出了高阶多项式算法和RBF神经网络算法两种温度补偿方法,并建立了相应的数学模型。论文还设计了不同温度条件下的实验以验证补偿效果,研究表明结合这两种算法能有效补偿光纤陀螺的温度漂移误差。此外,论文提供了详细的Python代码实现,包括数据预处理、补偿算法实现、有限元热分析模拟以及补偿效果的可视化。 适合人群:具备一定编程基础和物理基础知识的研究人员或工程师,尤其是从事惯性导航系统、光纤传感技术领域工作的人员。 使用场景及目标:①研究光纤陀螺在不同温度条件下的性能变化;②开发和优化温度补偿算法以提高光纤陀螺的精度;③利用提供的代码框架进行实验设计和数据分析,探索更有效的补偿策略。 其他说明:论文不仅提供了理论分析,还有具体的代码实现,有助于读者更好地理解和应用。文中涉及的补偿算法和有限元分析方法可以为其他相关领域的研究提供参考。此外,论文还讨论了温度误差的多物理场耦合机理、静态与动态补偿的综合效果以及工程实现中的关键技术瓶颈和解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值