11 |「异步任务与多线程」

前言

实践是最好的学习方式,技术也如此。

文章目录

    • 前言
    • 一、同步和异步的概念
      • 1、同步和异步任务
      • 2、线程
    • 二、Android 多线程与 Handler 机制
      • 1、分类
      • 2、原则
      • 3、Handler 机制
        • 1)问题(背景)
        • 2)Handler 异步通信系统
        • 3)消息传递流程
    • 三、代码举例

一、同步和异步的概念

1、同步和异步任务

  • 同步任务
    • 在执行程序时,如果一直没有收到执行结果,就一直等待,不继续往下执行,直到收到执行结果,才接着往下执行;
  • 异步任务
    • 在执行程序时,如果遇到需要等待的任务,就另外开辟一个子线程去执行它,自己继续往下执行其他程序。子线程有结果时,会将结果发送给主线程。异步任务的形式不影响程序的主要进程。

2、线程

  • 是什么
    • 就是一个执行过程,多线程即多个执行过程;
  • 为什么要有多线程
    • 程序中可能有多个任务,如果只有一个线程,那么就只能一个接着一个执行,就类似于同步执行任务,明显执行结果会比较慢,因为只有上一个任务执行完成,才能进行下一个。因此,需要多个线程来分别执行这些任务,即对应了上面的异步任务。

二、Android 多线程与 Handler 机制

1、分类

  • 主线程

    • 对于 Android App 程序。App 一启动,本身就是一个线程,这个线程被称为 主线程(main Thread);
    • 负责显示界面与用户进行实时交互(例如,用户点击一个按钮、输入文字,都需要程序进行响应处理);因为界面通常被称为 UI,所以,主线程又被称为 UI 线程。
  • 子线程

    • 除了主线程,剩下开辟的线程都称为子线程;
  • 类比生活中的例子

    • 场景:小明宴请客人
      • 主线程:小明;
      • 响应用户对界面的操作:小明接待客人;
      • 耗时操作:做饭;
      • 开启子线程:请一个保姆来做饭;

2、原则

  • 主线程不能执行网络请求/文件读写等耗时操作,就不能实时响应界面;
  • 子线程不能执行 UI 刷新(不能操作 UI 元素,操作任何一个控件);
  • 总结
    • 当遇到比较耗时的任务时,主线程可以开启一个子线程去执行,主线程接着执行主界面的响应任务,不影响用户的交互感受;类比,小明接待客人,请一个保姆去做饭,自己继续接待客人,不影响客人的感受;
    • 子线程不能更新 UI 界面,就像是保姆不能直接接待客人一样,对用户是不可见的;

3、Handler 机制

1)问题(背景)
  • 主线程中开启子线程,子线程执行任务完成将结果传递给主线程;子线程如何将结果(数据)传递给主线程,来实现主线程进行界面的改变?
2)Handler 异步通信系统
  • Handler 的英文名词解释:处理者;
  • 主要角色:程序员只需要了解 HandlerMessage 这两个角色即可,剩下两个角色都是安卓系统在底层已经封装好的;
    • Handler:类的名字;
    • Message:消息
      • 子线程执行任务完成将结果传递给主线程,传递的就是这个 Message 实体的对象;
    • MessageQueue:消息队列
    • Looper
      • 承担了主线程不时地查看邮箱中是否有消息的角色;
      • 从消息队列中拿消息,只要消息队列中有消息,就会一直不停的拿;
3)消息传递流程
  • 主线程在建立的时候就建立了上图所示的一套 Handler 系统,建立的过程是在底层进行的;
  • 子线程要传递给主线程消息,需要通过 Handler
    • 子线程会先拿到主线程的 Handler

    • Handler 通过sendMessage() 方法发送消息,消息发送至消息队列中(而不是直接发送给主线程);

      • 为什么不直接将消息发送给主线程?(时机的问题)
    • Looper 从消息队列中拿消息,将拿到的消息回传给 HandlerHandler 收到回传回来的消息之后就会执行 handlerMessage 方法(处理消息的方法);

  • 总结
    • 主线程的 Handler 系统进行消息流转;
    • 主线程会从系统中的消息队列中拿到消息交给自己,然后调用 HandleMessage 方法,就可以收到子线程传给主线程的消息了;

三、代码举例

  • 代码背景描述:选择选项框中对应城市的 item 实现查找对应城市的天气数据;
// 初始化
private void initView() {mSpinner = findViewById(R.id.sp_city);/*** 设置Adapter* 获取数据* 将自定义布局、数据与Adapter进行关联* 设置Spinner的Adapter*/mCities = getResources().getStringArray(R.array.cities);mSpAdapter = new ArrayAdapter<>(this, R.layout.sp_item_layout, mCities);mSpinner.setAdapter(mSpAdapter);mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {// 当Spinner中选中某一项时被调用@Overridepublic void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {// 选中城市后,会拿到选中城市名字,根据拿到的城市名字来查询对应城市的天气String selectCity = mCities[i];getWeatherCity(selectCity);  // 开启子线程}// 当Spinner没有选中任何项时被调用@Overridepublic void onNothingSelected(AdapterView<?> adapterView) {}});tvWeather = findViewById(R.id.tv_weather);tvAir = findViewById(R.id.air);tvTem = findViewById(R.id.tv_tem);tvTemLowHigh = findViewById(R.id.tv_tem_low_high);tvWin = findViewById(R.id.tv_win);ivWeather = findViewById(R.id.iv_weather);rlvFutyreWeather = findViewById(R.id.rlv_future_weather);
}
// 请求网络(开启一个子线程)
private void getWeatherCity(String selectCity) {// 开启子线程,请求网络new Thread(new Runnable() {@Overridepublic void run() {// 请求网络,拿到天气数据String weatherOfCity = NetUtil.getWeatherCity(selectCity);// 使用Handler将数据传递给主线程Message message = Message.obtain();  // 效率高,从消息池里拿消息,利于对象的重用message.what = 0;  // 标识哪个消息message.obj = weatherOfCity;  // 将数据放到消息中mHandler.sendMessage(message);  // 将消息发出去}}).start();
}
// 主线程处理子线程发送来的消息
private Handler mHandler = new Handler(Looper.myLooper()) {// 重写里面的方法 ctrl+o// 重写handleMessage方法@Overridepublic void handleMessage(@NonNull Message msg) {  // 接收handler发出的消息super.handleMessage(msg);if (msg.what == 0) {// 在主线程中拿到消息String weather = (String) msg.obj;Log.d("fan", "---主线程收到了天气数据---" + weather);// 解析JSONGson gson = new Gson();// 将JSON格式复杂的字符串解析成Java对象WeatherBean weatherBean = gson.fromJson(weather, WeatherBean.class);Log.d("fan", "---解析后的数据---" + weatherBean.toString());updateUiOfWeather(weatherBean);}}
};
  • 明确:主线程和子线程执行代码的顺序和代码的所属范围;
    • 子线程拿到主线程的 Handler,因为 Handler 本身属于是主线程的,所以处理消息(handlerMessage)也是在主线程中(属于主线程范围)
  • 红色箭头为主线程执行的代码,黄色框里的为子线程执行的代码范围,两者互不干涉,只执行自己范围内的代码,不能执行范围外的代码;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/726516.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

重塑生产格局:新质生产力引领下的新型工业操作系统和工业母机创新动向

新质生产力是创新起主导作用&#xff0c;摆脱传统经济增长方式、生产力发展路径&#xff0c;具有高科技、高效能、高质量特征&#xff0c;符合新发展理念的先进生产力质态。 **风口情报&#xff1a;**近日&#xff0c;中央经济工作会议首次提出“发展新质生产力”&#xff1b;…

作业1-32 P1059 [NOIP2006 普及组] 明明的随机数

题目 思路 根据题意&#xff0c;需要将读入的数据排序&#xff0c;去重。 参考代码 #include<bits/stdc.h> using namespace std; int n,a[5000],k;int main() {while(cin>>n){//读入数据for(int i0;i<n;i)cin>>a[i];sort(a,an);//排序int b[5000];in…

深度学习需要掌握哪些数学基础?

《深度学习的数学》这本书再合适不过了。作者罗纳德.T.纽塞尔&#xff08;Ronald T. Kneusel&#xff09;&#xff0c;拥有超过 20年的机器学习行业经验。 本书适合有一定深度学习基础、了解Python编程语言的读者阅读&#xff0c;也可作为用于拓展深度学习理论的参考书。 为什么…

CKA考试必备:解锁Pod封装多容器的高级技巧!

往期精彩文章 : 提升CKA考试胜算&#xff1a;一文带你全面了解RBAC权限控制&#xff01;揭秘高效运维&#xff1a;如何用kubectl top命令实时监控K8s资源使用情况&#xff1f;CKA认证必备&#xff1a;掌握k8s网络策略的关键要点提高CKA认证成功率&#xff0c;CKA真题中的节点维…

【MySQL】用户管理 -- 详解

如果我们只能使用 root 用户&#xff0c;这样存在安全隐患。这时就需要使用 MySQL 的用户管理。 一、 用户 1、用户信息 MySQL 中的用户都存储在系统数据库 MySQL 的 user 表中。 字段解释&#xff1a; host&#xff1a;表示这个用户可以从哪个主机登陆&#xff0c;如果…

【三】【SQL Server】如何运用SQL Server中查询设计器通关数据库期末查询大题

数据库学生选择1122 数据库展示 course表展示 SC表展示 student表展示 数据库学生选课1122_1 第一题 第二题 第三题 第四题 第五题 数据库学生选课1122_2 第六题 第七题 第八题 第九题 第十题 结尾 最后&#xff0c;感谢您阅读我的文章&#xff0c;希望这些内容能够对您有所启…

实践:qemu 运行 linux riscv with AIA(APLICIMSIC)

RISCV架构 Linux AIA支持 目标&#xff1a;在 Qemu 中运行一个支持 riscv aia 的 linux 翻译参考自&#xff1a;https://lwn.net/Articles/963231/ 文章日期&#xff1a;2024年2月22日&#xff0c;星期四&#xff08;截至2024年3月&#xff0c;最新&#xff09; 这个网站里在不…

Spring Boot工程集成验证码生成与验证功能教程

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

《Vite 报错》ReferenceError: module is not defined in ES module scope

ReferenceError: module is not defined in ES module scope 解决方案 postcss.config.js 要改为 postcss.config.cjs&#xff0c;也就是 .cjs 后缀。 原因解析 下图提示&#xff0c;packages.json 中的属性 type 设置为 module。所有 *.js 文件现在都被解释为 ESM&#xff…

电商店群系统的搭建需要用到的官方接口如何申请?

电商电子商务企业往往都会需要再很多平台上面铺货&#xff0c;上传商品。 高科技的今天&#xff0c;我们已经不需要手动一个个品去上传了。那通过官方接口&#xff0c;如何实现快速铺货呢&#xff1f; 1688官方开放平台的API接口类型众多&#xff0c;并不是所有的企业都能申请…

GitHub Pages部署静态页面

GitHub Pages是GitHub提供的静态页面托管服务&#xff0c;可以用来托管个人博客、项目文档等静态页面。GitHub Pages支持Jekyll&#xff0c;可以使用Jekyll构建博客&#xff0c;也可以使用其他静态页面生成器。现在GitHub Pages也在公测通过工作流部署静态页面&#xff0c;可以…

鸿蒙文章专题-2021年鸿蒙相关的文章废弃

#原因 至于为什么说2021年我的鸿蒙专栏的文章废弃了&#xff0c;只是说没有了参考意义&#xff0c;是因为鸿蒙4.0以前的版本语言从以Java为主过渡为以ArkTS为主。以前的Java版本的工程已经无法再使用了&#xff0c;后续的开发都必须以ArkTS开发语言为主。 其中而且整个项目结构…

三. 开发环境搭建

目录 一. Ubuntu 和 Windows 文件互传 1.1 VMware Tools 1.2 FileZilla 二. Ubuntu 下 NFS 和 SSH 服务开启 2.1 NFS 服务开启 ​编辑 2.2 SSH 服务开启 三. Ubuntu 交叉编译工具链安装 四. vscode的remote-ssh远程连接虚拟机 4.1 Windows的vscode安装 4.2 vscode远…

chatGPT的耳朵!OpenAI的开源语音识别AI:Whisper !

语音识别是通用人工智能的重要一环&#xff01;可以说是AI的耳朵&#xff01; 它可以让机器理解人类的语音&#xff0c;并将其转换为文本或其他形式的输出。 语音识别的应用场景非常广泛&#xff0c;比如智能助理、语音搜索、语音翻译、语音输入等等。 然而&#xff0c;语音…

专题1 - 双指针 - leetcode 11. 盛最多水的容器

leetcode 11. 盛最多水的容器 1. leetcode 11. 盛最多水的容器1. 题目详情1. 原题链接2. 基础框架 2. 解题思路1. 题目分析2. 算法原理3. 时间复杂度 3. 代码实现4. 知识与收获 1. leetcode 11. 盛最多水的容器 1. 题目详情 给定一个长度为 n 的整数数组 height 。有 n 条垂线…

分享一波非标设计资源合集

01 非标电表箱柜 本项目为创博智慧云产业研发中心的非标配电箱、电表箱设计原理图&#xff0c;地块一层含dwg图纸一份&#xff0c;包括配电箱壳体尺寸、原理图、接线图等20多种设计图纸。 02 住宅楼高压 低压 非标箱原理和箱体图 本图纸为高级住宅小区高低压非标箱设计原理…

Unity:Animation 三 Playable、ImportModel

目录​​​​​​​ 1. Playables API 1.1 Playable vs Animation 1.2 Advantages of using the Playables API 1.3 PlayableGraph Visualizer 2. Creating models outside of Unity 2.1 Preparing your model files for export 2.1.1 Scaling factors 2.1.2 优化模型文…

开源文生图大模型Playground v2.5发布:超越SD、DALL·E 3和 Midjourney

前言 在AI技术迅速发展的今天&#xff0c;文生图模型成为了艺术创作、设计创新等领域的重要工具。Playground v2.5的发布&#xff0c;不仅在技术上取得了突破&#xff0c;更在开源文化的推广与实践上迈出了重要一步。 Huggingface模型下载&#xff1a;https://huggingface.co/…

图论练习5

Going Home Here 解题思路 模板 二分图最优匹配&#xff0c;前提是有完美匹配&#xff08;即存在一一配对&#xff09;左右集合分别有顶标&#xff0c;当时&#xff0c;为有效边&#xff0c;即选中初始对于左集合每个点&#xff0c;选择其连边中最优的&#xff0c;然后对于每…

Sqli-labs靶场第18关详解[Sqli-labs-less-18]自动化注入-SQLmap工具注入

Sqli-labs-Less-18 通过测试发现&#xff0c;在登录界面没有注入点&#xff0c;通过已知账号密码admin&#xff0c;admin进行登录发现&#xff1a; 返回了User Agent&#xff0c;设想如果在User Agent尝试加上注入语句&#xff08;报错注入&#xff09;&#xff0c;测试是否会…