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

一、通过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>

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

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

  1. Android App开发手机阅读中实现平滑翻书效果和卷曲翻书动画实战(附源码 简单易懂 可直接使用)

    需要图片集和源码请点赞关注收藏后评论区留言~~~ 一.平滑翻书效果 与纸质书籍类似,手机上的电子书也有很多页,逐页浏览可采用翻页视图,然而翻页视图犹如一幅从左到右的绵长画卷,与现实生活中上下层叠的书籍 ...

  2. Android App开发手机阅读中PDF文件渲染器的讲解及使用(附源码 简单易懂)

    需要源码和图片集请点赞关注收藏后评论区留言~~~ 一.PDF文件渲染器 Android集成了PDF的渲染操作,从很大程度上方便了开发者,这个PDF文件渲染器便是PdfRenderer.渲染器允许从存储 ...

  3. Android App开发之自定义图形中位图与图形互转、剪裁图形内部区域、给图形添加部件的讲解及实战(附源码 简单易懂)

    需要图片和源码点赞关注收藏后评论区留言~~~ 一.位图与图形互转 Drawable用于在界面上展示图片,Bitmap用于加工图像数据,所以两者之间的转换非常有必要,位图图形BitmapDrawable ...

  4. 前端小白也能快速学会的博客园博客美化全攻略[附源码]

    前端小白也能快速学会的博客园博客美化全攻略[附源码] 文章目录 前端小白也能快速学会的博客园博客美化全攻略[附源码] 美化方法论简介 准备工作 js权限申请 如何模仿一个博客园的自定义风格(样式css ...

  5. 【Android App】物联网中查看手机支持的传感器及实现摇一摇功能-加速度传感器(附源码和演示 超详细)

    需要源码请点赞关注收藏后评论区留言~~~ 一.传感器的种类 传感器Sensor是一系列感应器的总称,是Android设备用来感知周围环境和运动信息的工具. 因为具体的感应信息依赖于相关硬件,所以虽然A ...

  6. Android Studio App开发之利用图像解码器ImageDecoder播放GIF动图、Webp、HEIF图片(附源码 简单实用)

    需要源码和图片集请点赞关注收藏后评论区留言~~~ 一.图像解码器ImageDecoder 早期的Android只支持3种图像格式,分别是JPEG,PNG,GIF 虽然这三类图片都能在ImageView ...

  7. 可测含多进程的app-- python调用adb命令获取Android App应用的性能数据:CPU、GPU、内存、电池、耗电量(含python源码)

    可测含多进程的app–Python–通过adb命令获取Android App应用的性能数据:CPU.GPU.内存.电池.耗电量,并与Perfdog取值对比结果 1.原理 python脚本通过os.po ...

  8. ANDROID物联网开发从入门到实战附源码

    本书从获取源码和搭建应用开发环境开始讲起,依次讲解了基础知识篇.数据传输篇.信息识别篇.传感器应用篇和技术提高篇这 5大部分内容. 目录 第1篇 基础知识篇 第1章 Android系统介绍 2 1.1 ...

  9. Android小项目之--前台界面与用户交互的对接 进度条与拖动条(附源码)

    都知道水果公司(苹果)是己尊重用户体验著称的公司,其设计的产品人性化十足,不得不令后来者赞叹,竞相模仿.iphone的成功就是其典型的案例,做为其移动系统的死对头 Google 想要在市场上分得一杯羹 ...

  10. PyTorch使用快速梯度符号攻击(FGSM)实现对抗性样本生成(附源码和数据集MNIST手写数字)

    需要源码和数据集请点赞关注收藏后评论区留言或者私信~~~ 一.威胁模型 对抗性机器学习,意思是在训练的模型中添加细微的扰动最后会导致模型性能的巨大差异,接下来我们通过一个图像分类器上的示例来进行讲解, ...

最新文章

  1. ideal如何创建dynamic web project
  2. 字节跳动AI Lab社招以及实习生内推
  3. DOMContentLoaded与load的区别
  4. 数据结构练习 00-自测1. 打印沙漏(20)
  5. mysql启动warning: World-writable config file
  6. MyEclipse使用总结——使用MyEclipse打包带源码的jar包
  7. 1.IT-解决方案-1-FTP
  8. 前端学习(774):查文档
  9. CentOS7的安装和配置
  10. D3D学习摘记(I)上
  11. 【TSP】基于matlab模拟退火算法求解旅行商问题【含Matlab源码 136期】
  12. 人工智能原理与方法作业1
  13. java来电报名字的软件_读短信来电报姓名
  14. mysql多主集群_MYSQL-galera多主集群
  15. nbu 7.5备份oracle,NBU7.5备份oracle
  16. linux下罗技摄像头采集图片,linux下寻找罗技摄像头快看酷讯版驱动
  17. 重启共享文件服务器,windows server 2008 文件服务器不定期出现大量CLOSE_WAIT状态的连接,必须重启服务器,客户端才能访问共享。...
  18. 杰理AC692X系列---关于692x及693x的打开在线调EQ功能(4)
  19. 免费智能AI文章生成器-只需要输入关键词自动生成文章的软件
  20. Vieux-部分型号iPhone\iPad\iPod降级工具使用教程

热门文章

  1. 工作小结_2016年2月23日23:16:59
  2. 百看不如一练, 247 个 Python 实战案例(附源代码)
  3. 任正非:《一江春水向东流》
  4. vivado布线congestion拥塞
  5. 服务器搭建是基于操作系统的,服务器搭建是基于操作系统的
  6. 微商必看:快速加微信好友的技巧
  7. python调用打印机打印图片
  8. 参与openEuler社区不到1年,我成为了社区Maintainer……
  9. 合肥工业大学计算机网络期中考试,计算机网络实验报告合肥工业大学
  10. Android广告的Activity收集