运行有问题或需要源码请点赞关注收藏后评论区留言 ~~~
一、分线程通过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","黑人之死引发美国各地反种族主义运动", "印度运营商禁止华为中兴反遭诺基亚催债","贝鲁特发生大爆炸全球紧急救援黎巴嫩", "日本货轮触礁毛里求斯造成严重漏油污染"};@Overrideprotected 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);}@Overridepublic 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 {@Overridepublic 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" ><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>
创作不易 觉得有帮助请点赞关注收藏~~~