Android App网络通信中通过runOnUiThread快速操纵界面以及利用线程池Executor调度异步任务实战(附源码 简单易懂)

运行有问题或需要源码请点赞关注收藏后评论区留言私信~~~

一、通过runOnUiThread快速操纵界面

因为Android规定分线程不能够直接操纵界面,所以它设计了处理程序工具,由处理程序负责在主线程和分线程之间传递数据,如果分线程想刷新界面,就得向处理程序发送消息,由处理程序在handleMessage方法中操作控件

测试效果如下 可观察到新闻播报效果 可手动点击按钮控制新闻播报的开始与暂停

 

 

 代码如下

Java类

package com.example.network;import android.os.Bundle;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;import com.example.network.util.DateUtil;import java.util.Random;public class ThreadUiActivity extends AppCompatActivity {private TextView tv_message; // 声明一个文本视图对象private boolean isPlaying = false; // 是否正在播放新闻private String[] mNewsArray = { "北斗导航系统正式开通,定位精度媲美GPS","黑人之死引发美国各地反种族主义运动", "印度运营商禁止华为中兴反遭诺基亚催债","贝鲁特发生大爆炸全球紧急救援黎巴嫩", "日本货轮触礁毛里求斯造成严重漏油污染"};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_thread_ui);tv_message = findViewById(R.id.tv_message);findViewById(R.id.btn_start).setOnClickListener(v -> {if (!isPlaying) { // 如果不在播放就开始播放isPlaying = true;new Thread(() -> broadcastNews()).start(); // 启动新闻播放线程}});findViewById(R.id.btn_stop).setOnClickListener(v -> isPlaying = false);}// 播放新闻private void broadcastNews() {// 回到主线程(UI线程)操纵界面
//        runOnUiThread(new Runnable() {
//            @Override
//            public void run() {
//                String desc = String.format("%s\n%s %s", tv_message.getText().toString(),
//                        DateUtil.getNowTime(), "开始播放新闻");
//                tv_message.setText(desc);
//            }
//        });String startDesc = String.format("%s\n%s %s", tv_message.getText().toString(),DateUtil.getNowTime(), "开始播放新闻");// 回到主线程(UI线程)操纵界面runOnUiThread(() -> tv_message.setText(startDesc));while (isPlaying) { // 正在播放新闻try {Thread.sleep(2000); // 睡眠两秒(2000毫秒)} catch (InterruptedException e) {e.printStackTrace();}String runDesc = String.format("%s\n%s %s", tv_message.getText().toString(),DateUtil.getNowTime(), mNewsArray[new Random().nextInt(5)]);// 回到主线程(UI线程)操纵界面runOnUiThread(() -> tv_message.setText(runDesc));}String endDesc = String.format("%s\n%s %s", tv_message.getText().toString(),DateUtil.getNowTime(), "新闻播放结束,谢谢观看");// 回到主线程(UI线程)操纵界面runOnUiThread(() -> tv_message.setText(endDesc));isPlaying = false;}}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><Buttonandroid:id="@+id/btn_start"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="开始播放新闻"android:textColor="@color/black"android:textSize="17sp" /><Buttonandroid:id="@+id/btn_stop"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="停止播放新闻"android:textColor="@color/black"android:textSize="17sp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="180dp"android:orientation="vertical" ><TextViewandroid:id="@+id/tv_message"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingLeft="5dp"android:scrollbars="vertical"android:gravity="left|bottom"android:maxLines="9"android:textColor="@color/black"android:textSize="15sp" /></LinearLayout></LinearLayout>

二、利用线程池Executor调度异步任务

线程池中的线程数量最好由开发者分配,这时需要使用ThreadPoolExecutor的构造方法创建线程池对象,下面是构造方法的参数说明

int corePoolSize 线程池的最小线程个数

int maximumPoolSize 线程池的最大线程个数

long keepAliveTime 非核心线程在无任务时的等待时长 若超过该时间仍未分配任务 则该线程自动结束

TimeUnit unit 时间单位 包括秒 毫秒和微秒

下面是它的常用方法

execute 向执行队列添加指定的任务

remove 移除指定任务

shutdown 关闭线程池

isTerminated 判断线程池是否关闭

setCorePoolSize 设置线程池的最小线程个数

getPoolSize 获取当前的线程个数

getActiveCount 获取当前的活动线程个数 

各种线程池的执行结果如下图  单线程则每隔两秒打印一行日志  多线程则每秒打印四行日志 无限制个数的则一秒内把所有线程打印出来 

 

 

 

 代码如下

Java类

package com.example.network;import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import com.example.network.util.DateUtil;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class ThreadExecutorActivity extends AppCompatActivity {private final static String TAG = "ThreadExecutorActivity";private TextView tv_desc; // 声明一个文本视图对象private String mDesc = "";private ExecutorService mThreadPool; // 声明一个线程池对象@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_thread_executor);tv_desc = findViewById(R.id.tv_desc);initPoolSpinner(); // 初始化线程池下拉框}// 初始化线程池下拉框private void initPoolSpinner() {ArrayAdapter<String> poolAdapter = new ArrayAdapter<>(this,R.layout.item_select, poolArray);Spinner sp_pool = findViewById(R.id.sp_pool);sp_pool.setPrompt("请选择线程池类型");sp_pool.setAdapter(poolAdapter);sp_pool.setOnItemSelectedListener(new PoolSelectedListener());sp_pool.setSelection(0);}private String[] poolArray = {"无线程池", "单线程线程池", "多线程线程池", "无限制线程池", "自定义线程池", "主线程"};class PoolSelectedListener implements AdapterView.OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {if (mThreadPool != null) {//mThreadPool.shutdown(); // 停止接收新任务,原来的任务继续执行mThreadPool.shutdownNow(); // 停止接收新任务,原来的任务停止执行}mDesc = poolArray[arg2] + "正在处理";if (arg2 == 1) { // 单线程线程池mThreadPool = Executors.newSingleThreadExecutor();startPoolTask(); // 开始执行线程池处理} else if (arg2 == 2) { // 多线程线程池mThreadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(4);startPoolTask(); // 开始执行线程池处理} else if (arg2 == 3) { // 无限制线程池mThreadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();startPoolTask(); // 开始执行线程池处理} else if (arg2 == 4) { // 自定义线程池mThreadPool = new ThreadPoolExecutor(2, 5, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(19));startPoolTask(); // 开始执行线程池处理} else if (arg2 == 5) { // 主线程。注意耗时任务会堵塞主线程if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {for (int i = 0; i < 20; i++) {// 创建一个新的消息分发任务MessageRunnable task = new MessageRunnable(i);getApplication().getMainExecutor().execute(task); // 命令主线程执行该任务}} else {Toast.makeText(ThreadExecutorActivity.this,"主线程需要Android9或更高版本", Toast.LENGTH_SHORT).show();}}}public void onNothingSelected(AdapterView<?> arg0) {}}// 开始执行线程池处理private void startPoolTask() {for (int i = 0; i < 20; i++) {// 创建一个新的消息分发任务MessageRunnable task = new MessageRunnable(i);mThreadPool.execute(task); // 命令线程池执行该任务}}// 定义一个消息分发任务private class MessageRunnable implements Runnable {private int mIndex;public MessageRunnable(int index) {mIndex = index;}@Overridepublic void run() {runOnUiThread(() -> {mDesc = String.format("%s\n%s 当前序号是%d", mDesc, DateUtil.getNowTime(), mIndex);tv_desc.setText(mDesc);});try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}}}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="40dp" ><TextViewandroid:layout_width="wrap_content"android:layout_height="match_parent"android:paddingLeft="5dp"android:gravity="center"android:text="线程池类型:"android:textColor="@color/black"android:textSize="17sp" /><Spinnerandroid:id="@+id/sp_pool"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="left|center"android:spinnerMode="dialog" /></LinearLayout><ScrollViewandroid:layout_width="match_parent"android:layout_height="wrap_content" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" ><TextViewandroid:id="@+id/tv_desc"android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingLeft="5dp"android:textColor="@color/black"android:textSize="17sp" /></LinearLayout></ScrollView></LinearLayout>

创作不易 觉得有帮助请点赞关注收藏~~~

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

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

相关文章

记一次基于模板方法的设计开发过程

1、背景 本人做抵押贷金融系统开发&#xff0c;最近在开发过程中&#xff0c;遇到一个新的需求&#xff0c;公司和原第三方支付公司有一定的矛盾&#xff0c;造成支付能力支持不足&#xff0c;公司内部进行的新支付系统的搭建&#xff0c;所以需要将原支付功能对接到新支付功能…

2022 读书总结

2022 年主要阅读了文学类和理财类书籍&#xff0c;增加了几本杂项书籍&#xff0c;具体如下&#xff1a; 文史类 4 本 《软技能 2-软件开发者职业生涯指南》- 约翰.森梅兹《三体&#xff1a;黑暗森林》-刘慈欣《三体&#xff1a;死神永生》-刘慈欣《浪潮之巅》- 吴军理财类 7 本…

派森小镇(五)帮助

雾霭沉沉&#xff0c;水波澄碧。在一处悠远僻静的地方上有一个神奇的小镇&#xff0c;小镇的名字叫派森镇。小镇的前面有一条河&#xff0c;碧蓝的水映出小镇周围水墨画般朦胧的世界。 小镇上的人一出生就拥有特殊的技能&#xff0c;他们中的每一个人都是python的成员&#xff…

零基础 Amazon Web Services (AWS) 入门教程图文版(一)

现在小站唯一的流量都靠AWS这个关键词了,刚好要用AWS重新建站,所以从头开始记录一遍吧。 所谓零基础,就是你可以没有任何AWS使用经历,仍然能够按照教程操作下去。所谓图文版,就是建议手机用户在没有连Wifi的情况下尽量不要查看全文。图片一般都有大图,看不清的可以点击查…

Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day22,linux内核视频教程

优秀问答摘自&#xff1a;https://ask.csdn.net/questions/1101634 两者的共同点&#xff1a; 都是用来协调多线程对共享对象、变量的访问 都是可重入锁&#xff0c;同一线程可以多次获得同一个锁 都保证了可见性和互斥性 两者的不同点&#xff1a; ReentrantLock 显示的获…

百万奖金悬赏大模型不擅长的任务!这 11 个任务模型越大,效果越差!

夕小瑶科技说 原创 作者 | 智商掉了一地、Python 去年咱们在介绍百万悬赏时提到&#xff0c;“海量资源砸出的大模型真的会一直那么香吗&#xff1f;”&#xff0c;目前来看&#xff0c;自打 ChatGPT 横空出世引领一众大模型开辟新的生活和工作方式以来&#xff0c;还是挺香的…

三本-安全岗-面经总结(多多面经)

三月之前都不知道暑期实习是什么东西&#xff0c;导致错过很多机会&#xff0c;3月末才迷迷糊糊的准备面试&#xff0c;信息差跟环境真的很重要&#xff0c;周边没一个投暑期实习的同学&#xff0c;学校也没有任何提醒&#xff0c;自己一个人摸爬滚投实习、准备、面试&#xff…

数据万象 | AIGC 存储内容安全解决方案

AIGC&#xff08;人工智能生产内容&#xff09; 已经成为与PGC&#xff08;专业生产内容&#xff09;、UGC&#xff08;用户生产内容&#xff09;并驾齐驱的内容生产方式。由于 AI 的特性&#xff0c;AIGC在创意、个性化、生产效率等方面具有独特的优势&#xff0c;这些优势可以…

没关系,前端还死不了

前言 网络上的任何事情都可以在《乌合之众》书中找到答案。大众言论没有理性&#xff0c;全是极端&#xff0c;要么封神&#xff0c;要么踩死。不少人喷前端&#xff0c;说前端已死&#xff1f;前端内卷&#xff1f;前端一个月800包吃住&#xff1f; 对此我想说&#xff0c;“…

Android程序员秋招就业你准备好了嘛?

前言 秋招即将到了&#xff0c;又到了一年一度的大型“程序猿就业典礼”。 从事IT行业那么多年&#xff0c;我自己也经历过&#xff0c;也见过很多求职路上的人生百态。 当初我也是从一个不知名的“打工人”&#xff0c;到如今成为了鹅厂的一员… 这其中经历了太多太多&…

又一AIGC独角兽!帮企业定制大模型,营销物料生成发布全包,Adobe前CTO创办

衡宇 发自 凹非寺量子位 | 公众号 QbitAI 全球范围内的投资者纷纷重金押注AI初创公司这事儿&#xff0c;已经越来越掩藏不住了&#xff01; ——又一家AI初创公司刚刚长成独角兽&#xff0c;这距离其第一次公开露面只过去4个月时间。 最新消息&#xff0c;Adobe前CTO Abhay Par…

“意识机器”初探:如何让大语言模型具备自我意识?

导语 什么是意识&#xff1f;现在的大语言模型具备意识了吗&#xff1f;我们能否造出具备自我意识的机器&#xff1f;在集智俱乐部「后ChatGPT」读书会&#xff0c;北京师范大学系统科学学院教授、集智俱乐部创始人张江老师回顾了意识科学和意识建模领域的进展&#xff0c;认为…

【人工智能AI2.0】清华发布了 ChatGLM-6B 中国大模型5支学术界团队和10大产业界力量介绍

ChatGLM 简介 https://chatglm.cn/login 目录 ChatGLM 简介 ChatGLM 特点 ChatGLM 基于智谱 AI GLM-130B

从脑科学角度解析GPT4及人工智能

来源&#xff1a;图灵教育 本文内容整理自图灵社区直播《对谈 | 刘江 刘嘉&#xff1a;从脑科学 人工智能角度讲透 GPT-4》 刘嘉&#xff0c;清华大学基础科学讲席教授&#xff0c;清华大学心理学系系主任&#xff0c;清华大学脑与智能实验室首席研究员 未来是什么样子&#…

缠论指标缠论指标

点击领取&#xff1a;缠论指标 支持平台 01 通达信(电脑手机&#xff09; 通达信版本简介 02 01 基础版功能&#xff1a; 支持缠论自动分笔&#xff0c;自动线段&#xff0c;显示笔中枢&#xff08;蓝色&#xff09;&#xff0c;线段中枢&#xff08;橙色&#xff09;&am…

tushareAPI获取股票沪深指数

上证指数历史数据采集 ID&#xff1a;503658 代码 # # 导入tushare import tushare as ts # 初始化pro接口 pro ts.pro_api(你自己的TOKEN)# 拉取数据 df pro.index_daily(**{"ts_code": "000001.SH","trade_date": "","st…

同花顺_代码解析_技术指标_P、Q

本文通过对同花顺中现成代码进行解析&#xff0c;用以了解同花顺相关策略设计的思想 目录 PBX PRICEOSC PSY PSYFS PVT QACD QLCX QLDX PBX 瀑布线 PBX1:(收盘价的M1日移动平均收盘价的M1*2日简单移动平均收盘价的M1*4日简单移动平均)/3 PBX2:(收盘价的M2日移动平均收…

最新和讯网社会责任指数(超详细指标)

1、数据来源&#xff1a;和讯网 2、时间跨度&#xff1a;2011-2020月6日 3、区域范围&#xff1a;全国 4、指标说明&#xff1a; 和讯网社会责任指标由50个细分指标构成&#xff0c;全体数据量巨大。费了好大功夫才将这些数据爬取下来&#xff0c;有需要的朋友千万不要错过…

同花顺_代码解析_技术指标_T、U

本文通过对同花顺中现成代码进行解析&#xff0c;用以了解同花顺相关策略设计的思想 目录 TBR TRIX TRIXFS TWR UDL UOS TBR 新三价率 新三价率:100*上涨家数/(上涨家数下跌家数) MATBR1:TBR的M1日异同移动平均 MATBR2:TBR的M2日异同移动平均 1.指数仍处于下跌状态&a…

通达信下单接口获取指数成份股的步骤分享

通达信下单接口获取指数成份股的步骤分享&#xff1a; ContextInfo.get_sector() 接口&#xff1a;https://gitee.com/metatradeapi 用法&#xff1a; ContextInfo.get_sector(sector, realtime) 释义&#xff1a; 获取板块成份股&#xff0c;只支持取指数成份股 参数&…