android Handler如何使用 以及runable thread等问题

android Handler如何使用 以及runable thread等问题

前言

android 多线程中Handler如何使用 以及runable thread等问题时常困扰着我,一直没机会弄明白就将就过去,现在有机会好好捋捋这东西

一、Handler是什么?

handler是一个处理两个线程间通信的消息机制。最常见的就是绑定ui线程,然后再绑定一个自定义的线程,自定义线程执行完毕后发消息给主线程ui更新UI界面

二、Thread和runable的关系

Thread是runable的一个子类,一种具体实现。
Thread这种具体实现在每次实例化的时候都是单独的对象
而runable实例化多次后为同一个对象执行同一个任务
具体见这举例说明
线程可以自己RUN也可以用Handler.post

三、一个应用

package com.example.module_learn.androidfunc.network;

import com.example.module_learn.R;
import com.example.module_learn.androidfunc.network.util.DateUtil;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import android.text.method.ScrollingMovementMethod;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

/**
 * Created by ouyangshen on 2017/11/11.
 */
@SuppressLint("HandlerLeak")
public class MessageActivity extends AppCompatActivity implements OnClickListener {
    private TextView tv_message; // 声明一个文本视图对象
    private boolean isPlaying = false; // 是否正在播放新闻
    private int BEGIN = 0, SCROLL = 1, END = 2; // 0为开始,1为滚动,2为结束

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_message);
        // 从布局文件中获取名叫tv_message的文本视图
        tv_message = findViewById(R.id.tv_message);
        // 设置tv_message内部文字的对齐方式为靠左且靠下
        tv_message.setGravity(Gravity.LEFT | Gravity.BOTTOM);
        tv_message.setLines(8); // 设置tv_message高度为八行文字那么高
        tv_message.setMaxLines(8); // 设置tv_message最多显示八行文字
        // 设置tv_message内部文本的移动方式为滚动形式
        tv_message.setMovementMethod(new ScrollingMovementMethod());
        findViewById(R.id.btn_start_message).setOnClickListener(this);
        findViewById(R.id.btn_stop_message).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_start_message) { // 点击了开始播放新闻的按钮
            if (!isPlaying) {
                isPlaying = true;
                new PlayThread().start(); // 创建并启动新闻播放线程
            }
        } else if (v.getId() == R.id.btn_stop_message) { // 点击了结束播放新闻的按钮
            isPlaying = false;
        }
    }

    private String[] mNewsArray = {  
    };

    // 定义一个新闻播放线程
    private class PlayThread extends Thread {
        @Override
        public void run() {
            // 向处理器发送播放开始的空消息
            mHandler.sendEmptyMessage(BEGIN);
            while (isPlaying) {
                try {
                    sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Message message = Message.obtain(); // 获得一个默认的消息对象
                message.what = SCROLL; // 消息类型
                message.obj = mNewsArray[(int) (Math.random() * 30 % 5)]; // 消息描述
                mHandler.sendMessage(message); // 向处理器发送消息
            }
            isPlaying = true;
            try {
                sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            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);
        }
    };

}

在handleMessage里接收来自不同分线程发送过来的信息,然后调用主线程方法

延伸一下

android使用了AsyncTask来封装了Handler+Thread。就像是Ajax一样吧

总结

执行一个多线程任务的时候要注意制这个事件是否是有冲突的事件,合理的选中runable和thread进行安排。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不被定义的号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值