Android Studio App开发中多线程的讲解与实现新闻轮播滚动实战(附源码 超详细必看)

简介: Android Studio App开发中多线程的讲解与实现新闻轮播滚动实战(附源码 超详细必看)

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

一、分线程通过Handler操作界面

为了使App运行的更加流畅,多线程技术被广泛应用于App开发,由于Android规定只有主线程才能直接操作界面,因此分线程若想修改界面就要另想办法,这要求有一种在线程之间相互通信的机制,如果是主线程向分线程传递消息,可以在分线程的构造方法中传递参数,然而分线程向主线程传递消息并无捷径,为此Android设计了一个Message消息工具,通过结合Handler与Message能够实现线程间通信

由分线程向主线程传递消息的过程主要有四个步骤

1:在主线程中构造一个处理器对象 并启动分线程

2:在分线程中构造一个Message类型的消息包

3:在分线程中通过处理器对象将Message消息发出去

4:主线程的Handler对象处理接收到的消息

综合上面的四个线程通信步骤,接下来通过一个实验观察线程间通信的效果,下面便是利用多线程技术实现新闻滚动的例子

点击开始播放新闻后便会自动播放,每隔两秒钟弹出一条新闻

点击停止播放新闻则停止播放

根据以上的新闻播放效果,可以知道分线程的播放开始和播放结束指令都成功送到了主线程

代码如下

Java类

package com.example.chapter11;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.example.chapter11.util.DateUtil;
import java.util.Random;
@SuppressLint("HandlerLeak")
public class HandlerMessageActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView tv_message; // 声明一个文本视图对象
    private boolean isPlaying = false; // 是否正在播放新闻
    private int BEGIN = 0, SCROLL = 1, END = 2; // 0为开始,1为滚动,2为结束
    private String[] mNewsArray = { "北斗导航系统正式开通,定位精度媲美GPS",
            "黑人之死引发美国各地反种族主义运动", "印度运营商禁止华为中兴反遭诺基亚催债",
            "贝鲁特发生大爆炸全球紧急救援黎巴嫩", "日本货轮触礁毛里求斯造成严重漏油污染"
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_message);
        tv_message = findViewById(R.id.tv_message);
        findViewById(R.id.btn_start).setOnClickListener(this);
        findViewById(R.id.btn_stop).setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_start) { // 点击了开始播放新闻的按钮
            if (!isPlaying) { // 如果不在播放就开始播放
                isPlaying = true;
                new PlayThread().start(); // 创建并启动新闻播放线程
            }
        } else if (v.getId() == R.id.btn_stop) { // 点击了结束播放新闻的按钮
            isPlaying = false;
        }
    }
    // 定义一个新闻播放线程
    private class PlayThread extends Thread {
        @Override
        public void run() {
            mHandler.sendEmptyMessage(BEGIN); // 向处理器发送播放开始的空消息
            while (isPlaying) { // 正在播放新闻
                try {
                    sleep(2000); // 睡眠两秒(2000毫秒)
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Message message = Message.obtain(); // 获得默认的消息对象
                //Message message = mHandler.obtainMessage(); // 获得处理器的消息对象
                message.what = SCROLL; // 消息类型
                message.obj = mNewsArray[new Random().nextInt(5)]; // 消息描述
                mHandler.sendMessage(message); // 向处理器发送消息
            }
            mHandler.sendEmptyMessage(END); // 向处理器发送播放结束的空消息
            // 如果只要简单处理,也可绕过Handler,直接调用runOnUiThread方法操作界面
//            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);
//                }
//            });
            isPlaying = false;
        }
    }
    // 创建一个处理器对象
    private Handler mHandler = new Handler() {
        // 在收到消息时触发
        public void handleMessage(Message msg) {
            String desc = tv_message.getText().toString();
            if (msg.what == BEGIN) { // 开始播放
                desc = String.format("%s\n%s %s", desc, DateUtil.getNowTime(), "开始播放新闻");
            } else if (msg.what == SCROLL) { // 滚动播放
                desc = String.format("%s\n%s %s", desc, DateUtil.getNowTime(), msg.obj);
            } else if (msg.what == END) { // 结束播放
                desc = String.format("%s\n%s %s", desc, DateUtil.getNowTime(), "新闻播放结束");
            }
            tv_message.setText(desc);
        }
    };
}

时间类

package com.example.chapter11.util;
import android.annotation.SuppressLint;
import android.text.TextUtils;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
@SuppressLint("SimpleDateFormat")
public class DateUtil {
    // 获取当前的日期时间
    public static String getNowDateTime(String formatStr) {
        String format = formatStr;
        if (TextUtils.isEmpty(format)) {
            format = "yyyyMMddHHmmss";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(new Date());
    }
    // 获取当前的时间
    public static String getNowTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        return sdf.format(new Date());
    }
    // 获取当前的时间(精确到毫秒)
    public static String getNowTimeDetail() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
        return sdf.format(new Date());
    }
    public static String getNowDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        return sdf.format(new Date());
    }
    public static String getDate(Calendar calendar) {
        Date date = calendar.getTime();
        // 创建一个日期格式化的工具
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 将当前日期时间按照指定格式输出格式化后的日期时间字符串
        return sdf.format(date);
    }
    public static String getMonth(Calendar calendar) {
        Date date = calendar.getTime();
        // 创建一个日期格式化的工具
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        // 将当前日期时间按照指定格式输出格式化后的日期时间字符串
        return sdf.format(date);
    }
    public static Date formatString(String strTime) {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            date = sdf.parse(strTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return date;
    }
}

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>

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

相关文章
|
11月前
|
Android开发 Windows
Android studio 报错Connect to 127.0.0.1:8888 [/127.0.0.1] failed: Connection refused: connect(已解决)
这是一篇关于解决Android Studio报错“Connect to 127.0.0.1:8888 failed: Connection refused”的文章。问题通常因系统代理设置被Android Studio自动保存导致。解决方法是找到系统中Android Studio使用的gradle.properties文件(位于Windows的C:\Users\你的电脑用户名\.gradle或Mac的/Users/.{你的用户目录}/.gradle),删除或注释掉多余的代理配置后保存并重新Sync项目。希望此经验能帮助快速解决同类问题!
2231 36
|
11月前
|
Java Android开发
Android studio中build.gradle文件简单介绍
本文解析了Android项目中build.gradle文件的作用,包括jcenter仓库配置、模块类型定义、包名设置及依赖管理,涵盖本地、库和远程依赖的区别。
951 19
|
存储 缓存 安全
Android14 适配之——现有 App 安装到 Android14 手机上需要注意些什么?
Android14 适配之——现有 App 安装到 Android14 手机上需要注意些什么?
1335 0
|
传感器 物联网 Android开发
【Android App】物联网中查看手机支持的传感器及实现摇一摇功能-加速度传感器(附源码和演示 超详细)
【Android App】物联网中查看手机支持的传感器及实现摇一摇功能-加速度传感器(附源码和演示 超详细)
739 1
|
Android开发 网络架构
【Android App】检查手机连接WiFi信息以及扫描周围WiFi的讲解及实战(附源码和演示 超详细必看)
【Android App】检查手机连接WiFi信息以及扫描周围WiFi的讲解及实战(附源码和演示 超详细必看)
2279 1
|
XML 安全 Java
Android Studio App开发之广播组件Broadcast的讲解及实战(包括收发标准、有序、静态广播实现手机震动功能 附源码)
Android Studio App开发之广播组件Broadcast的讲解及实战(包括收发标准、有序、静态广播实现手机震动功能 附源码)
1209 0
|
XML Java 定位技术
【Android App】定位导航GPS中开启手机定位功能讲解及实战(附源码和演示 超详细)
【Android App】定位导航GPS中开启手机定位功能讲解及实战(附源码和演示 超详细)
1610 0
|
XML Java Android开发
Android App开发手机阅读中实现平滑翻书效果和卷曲翻书动画实战(附源码 简单易懂 可直接使用)
Android App开发手机阅读中实现平滑翻书效果和卷曲翻书动画实战(附源码 简单易懂 可直接使用)
1202 0
|
XML Java Android开发
Android App开发手机阅读中PDF文件渲染器的讲解及使用(附源码 简单易懂)
Android App开发手机阅读中PDF文件渲染器的讲解及使用(附源码 简单易懂)
638 0
|
XML Java Android开发
Android App开发手机阅读之使用贝塞尔曲线实现给主播刷礼物特效(附源码和演示视频 简单易懂 可直接使用)
Android App开发手机阅读之使用贝塞尔曲线实现给主播刷礼物特效(附源码和演示视频 简单易懂 可直接使用)
388 0

热门文章

最新文章