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

简介: 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",
            "黑人之死引发美国各地反种族主义运动", "印度运营商禁止华为中兴反遭诺基亚催债",
            "贝鲁特发生大爆炸全球紧急救援黎巴嫩", "日本货轮触礁毛里求斯造成严重漏油污染"
    };
    @Override
    protected 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" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <Button
            android: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" />
        <Button
            android: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>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:orientation="vertical" >
        <TextView
            android: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; // 声明一个线程池对象
    @Override
    protected 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;
        }
        @Override
        public 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" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:paddingLeft="5dp"
            android:gravity="center"
            android:text="线程池类型:"
            android:textColor="@color/black"
            android:textSize="17sp" />
        <Spinner
            android: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>
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
            <TextView
                android: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>

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

相关文章
|
2月前
|
XML Java 数据库
安卓项目:app注册/登录界面设计
本文介绍了如何设计一个Android应用的注册/登录界面,包括布局文件的创建、登录和注册逻辑的实现,以及运行效果的展示。
159 0
安卓项目:app注册/登录界面设计
|
19天前
|
数据采集 网络协议 算法
移动端弱网优化专题(十四):携程APP移动网络优化实践(弱网识别篇)
本文从方案设计、代码开发到技术落地,详尽的分享了携程在移动端弱网识别方面的实践经验,如果你也有类似需求,这篇文章会是一个不错的实操指南。
44 1
|
2月前
|
网络协议 Shell 网络安全
解决两个 Android 模拟器之间无法网络通信的问题
让同一个 PC 上运行的两个 Android 模拟器之间能相互通信,出(qiong)差(ren)的智慧。
24 3
|
2月前
|
安全 网络安全 Android开发
深度解析:利用Universal Links与Android App Links实现无缝网页至应用跳转的安全考量
【10月更文挑战第2天】在移动互联网时代,用户经常需要从网页无缝跳转到移动应用中。这种跳转不仅需要提供流畅的用户体验,还要确保安全性。本文将深入探讨如何利用Universal Links(仅限于iOS)和Android App Links技术实现这一目标,并分析其安全性。
273 0
|
3月前
|
XML 数据库 Android开发
10分钟手把手教你用Android手撸一个简易的个人记账App
该文章提供了使用Android Studio从零开始创建一个简单的个人记账应用的详细步骤,包括项目搭建、界面设计、数据库处理及各功能模块的实现方法。
|
8天前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
在数字化时代,网络安全和信息安全已成为我们生活中不可或缺的一部分。本文将介绍网络安全漏洞、加密技术和安全意识等方面的知识,并提供一些实用的技巧和建议,帮助读者更好地保护自己的网络安全和信息安全。
|
1天前
|
存储 安全 网络安全
云计算与网络安全:云服务、网络安全、信息安全等技术领域的融合与挑战
随着云计算技术的飞速发展,越来越多的企业和个人开始使用云服务。然而,云计算的广泛应用也带来了一系列网络安全问题。本文将从云服务、网络安全、信息安全等方面探讨云计算与网络安全的关系,分析当前面临的挑战,并提出相应的解决方案。
14 3
|
7天前
|
安全 算法 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
在当今数字化时代,网络安全和信息安全已经成为了全球关注的焦点。随着技术的发展,网络攻击手段日益狡猾,而防范措施也必须不断更新以应对新的挑战。本文将深入探讨网络安全的常见漏洞,介绍加密技术的基本概念和应用,并强调培养良好安全意识的重要性。通过这些知识的分享,旨在提升公众对网络安全的认识,共同构建更加安全的网络环境。
|
6天前
|
存储 安全 网络安全
云计算与网络安全:探索云服务、网络安全和信息安全的交汇点
在数字化时代,云计算已成为企业和个人存储、处理数据的关键技术。然而,随着云服务的普及,网络安全问题也日益凸显。本文将深入探讨云计算与网络安全的关系,分析云服务中的安全挑战,并提出相应的解决方案。同时,我们还将介绍一些实用的代码示例,帮助读者更好地理解和应对网络安全问题。
|
9天前
|
安全 算法 网络协议
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
在数字时代,网络安全和信息安全已经成为了我们生活中不可或缺的一部分。本文将介绍网络安全漏洞、加密技术和安全意识等方面的内容,帮助读者更好地了解网络安全的重要性和应对措施。通过阅读本文,您将了解到网络安全的基本概念、常见的网络安全漏洞、加密技术的原理和应用以及如何提高个人和组织的网络安全意识。