Android中关于Handler的一些知识点

Handler

一.为什么要用Handler

1.主线程不能有耗时操作
2.子线程不能更新UI

二.什么是Handler

是处理异步消息的核心类(异步:不同的线程做不同的事)

三.什么是Looper

1.在安卓中创建出的普通线程默认是没有循环消息的,run方法执行完毕,线程也就结束了
2.如果让线程不停的循环工作时,可以使用Looper,将普通线程变成循环工作线程

四.什么是Message Queue

1.当创建Looper时,将会自动创建出Message Queue
2.一个线程中只会存在一个Looper和一个Message Queue
3.当Message Queue中有消息时,Looper将从Message Queue中取出消息

五.Handler怎么用
Handler的工作原理

子线程通过Handler发送消息到Message Queue,然后Looper从Message Queue拿出消息让主线程处理

Handler其中一个作用

让子线程通过UI线程通信来更新UI

下面是一个简单模仿下载的例子:
布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.myapplication.DownLoadActivity">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="30sp"
        android:text="准备下载"
        android:id="@+id/zhunbei_tv"
        android:layout_gravity="center"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:id="@+id/start_btn"
        android:text="开始下载"
        android:textSize="25sp"/>

</LinearLayout>

主类:

package com.example.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class DownLoadActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView zhunbei_tv;
    private Button start_btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_down_load);

        bindID();
    }

    private void bindID() {
        zhunbei_tv = findViewById(R.id.zhunbei_tv);
        zhunbei_tv.setOnClickListener(this);

        start_btn = findViewById(R.id.start_btn);
        start_btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.start_btn:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        zhunbei_tv.setText("下载完成");
                    }
                }).start();

                break;
        }

    }
}

但是这样写会报错,因为子线程不能更新UI.错误如下:

这里写图片描述

下面是改正后的主类:

package com.example.myapplication;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class DownLoadActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView zhunbei_tv;
    private Button start_btn;
    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            zhunbei_tv.setText("下载完成");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_down_load);

        bindID();
    }

    private void bindID() {
        zhunbei_tv = findViewById(R.id.zhunbei_tv);
        zhunbei_tv.setOnClickListener(this);

        start_btn = findViewById(R.id.start_btn);
        start_btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.start_btn:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        handler.sendEmptyMessage(1);
                    }
                }).start();
                break;
        }
    }
}

效果图:
这里写图片描述
五秒后
这里写图片描述

创建Message传值有两种方式:建议用第一种,第二个比较耗时
第一种:

Message msg=handler.obtainMessage();

第二种:

Message msg=new Message();

这是一个线程

new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                           while (time > 0) {
                                handler.sendEmptyMessage(time);
                                time--;
                                Thread.sleep(1000);
                            }

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        Message msg=handler.obtainMessage();
                        msg.obj="倒计时完成";
                        handler.sendMessage(msg);
                    }
                }).start();
六.案例解析——倒计时Demo

1.布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.myapplication.DownLoadActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/zhunbei_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="倒数计时"
            android:textSize="30sp" />

        <EditText
            android:id="@+id/daotime"
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:textSize="25sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:gravity="center_horizontal|center_vertical"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/start_time"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center"
            android:textSize="30sp" />

    </LinearLayout>

    <Button
        android:id="@+id/start_btn"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="开始倒计时"
        android:textSize="25sp" />

</LinearLayout>

布局文件的效果图:这里写图片描述
2.activity类

  • 绑定id
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_down_load);

        bindID();
    }

    private void bindID() {
        daotime = findViewById(R.id.daotime);
        start_time = findViewById(R.id.start_time);

        zhunbei_tv = findViewById(R.id.zhunbei_tv);
        zhunbei_tv.setOnClickListener(this);

        start_btn = findViewById(R.id.start_btn);
        start_btn.setOnClickListener(this);
    }
  • 给按钮添加点击事件

要实现View.OnClickListener 接口

public class DownLoadActivity extends AppCompatActivity implements View.OnClickListener {
 switch (view.getId()) {
            case R.id.start_btn:
            break;
  • 创建handler方法
private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };
  • 创建一个线程,里面使用handler发送消息, 在EditText控件得出来的界面上输入一个数字,按下按钮
switch (view.getId()) {
            case R.id.start_btn:
                start_time.setText(daotime.getText());
                time=Integer.parseInt(daotime.getText().toString());
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                           while (time > 0) {
                                handler.sendEmptyMessage(time);
                                time--;
                                Thread.sleep(1000);
                            }

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        Message msg=handler.obtainMessage();
                        msg.obj="倒计时完成";
                        handler.sendMessage(msg);
                    }
                }).start();

                break;
        }
  • 接收消息,等到时间倒数完毕,就会显示倒计时完成
private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.obj!=null){
                String result= (String) msg.obj;
                start_time.setText(result);
            }else {
                start_time.setText(msg.what + "秒");
            }

        }
    };

效果图:这里写图片描述
我输的是十秒,十秒之后的效果图:这里写图片描述
如果有什么不懂,下面是完整代码

package com.example.myapplication;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class DownLoadActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView zhunbei_tv, start_time;
    private Button start_btn;
    private EditText daotime;
    private int time;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.obj!=null){
                String result= (String) msg.obj;
                start_time.setText(result);
            }else {
                start_time.setText(msg.what + "秒");
            }

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_down_load);

        bindID();
    }

    private void bindID() {
        daotime = findViewById(R.id.daotime);
        start_time = findViewById(R.id.start_time);

        zhunbei_tv = findViewById(R.id.zhunbei_tv);
        zhunbei_tv.setOnClickListener(this);

        start_btn = findViewById(R.id.start_btn);
        start_btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.start_btn:
                start_time.setText(daotime.getText());
                time=Integer.parseInt(daotime.getText().toString());
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                           while (time > 0) {
                                handler.sendEmptyMessage(time);
                                time--;
                                Thread.sleep(1000);
                            }

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        Message msg=handler.obtainMessage();
                        msg.obj="倒计时完成";
                        handler.sendMessage(msg);
                    }
                }).start();

                break;
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值