使用Handler实现进度条倒计时,轮播广告,子线程发送处理消息

使用Handler实现进度条倒计时,轮播广告,子线程发送处理消息,第1张

使用Handler实现进度条倒计时,轮播广告,子线程发送处理消息 1 背景

在Android中,主线程负责管理与UI相关的事件;在自己创建的子线程中,不能对UI组件进行 *** 作。
例如,如下代码在单击按钮时创建新线程,这时改变文本框的显示文本会crash:

public class MainActivity extends AppCompatActivity {
    protected void onCreate() {
        ...
        button.setonClickListener(new View.onClickListener( {
            public void onClick(View v) {
                Thread thread = new Thread(new Runnable()) {
                    public void run() {
                        textView.setText("xxxxxxx");
                    }
                });
                thread.start();
            }
        });
    }
}

因此,Android引入Handler消息机制,来实现在新创建的线程中 *** 作UI。

2 Handler与Looper,MessageQueue的关系

关于详细的实现原理请参考老罗的讲解:

Android应用程序的消息处理机制(MessageQueue,Looper,Handler)_u012906122的专栏-CSDN博客

Handler类:
(1)在任意线程中发送消息
通过调用Handler的sendMessage()将消息发送到MessageQueue中。
(2)在主线程中获取并处理消息
覆写Handler类的handleMessage()方法。当Looper循环到该Message时,会回调Handler的handleMessage()处理消息。
Looper类:
管理MessageQueue。每个线程只能有一个Looper,loop()方法负责读取MessageQueue中的消息,读取到消息后把消息传给Handler进行处理。
Message类:
(1)Message:通过Handler发送和处理的消息对象
(2)MessageQueue:FIFO消息队列。

Handler与Looper,MessageQueue的关系如下:

一个线程对应一个Looper对象,一个Looper对象对应一个MessageQueue,MessageQueue用于存放Message。
Handler发送Message给Looper管理的MessageQueue,Looper又从MessageQueue中取出消息,给Handler处理。
因此,如果要在程序中使用Handler,必须在当前线程中有一个Looper对象。线程中的Looper对象有以下两种创建方式:
(1)UI主线程中,系统默认已经初始化一个Looper对象了,程序可以直接创建Handler,发送和处理消息。
(2)子线程中,需要手动创建一个Looper对象,并通过loop()启动Looper。
[1]调用Looper的prepare()来为当前线程创建Looper对象,同时创建MessageQueue。
[2]创建Handler实例,覆写handleMessage()方法。
[3]调用Looper的loop()方法启动Looper。

注意:一个线程中,只有一个Looper和MessageQueue,但可以有多个Handler。

3 使用Handler实现进度条倒计时

发送和处理消息都是在主线程
MainActivity.java

public class MainActivity extends Activity {
    public final static String TAG = "ProgressBar";

    final int TIME = 20;   

    final int TIMER_MSG = 0x001;   

    private ProgressBar timer;    

    private int mProgressStatus = 0;    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        timer = (ProgressBar) findViewById(R.id.timer);      
        handler.sendEmptyMessage(TIMER_MSG);    //发送消息,启动进度条
        Log.d(TAG, "onCreate tid:" + android.os.Process.myTid());
    }
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            //当前进度大于0
            if (TIME - mProgressStatus > 0) {
                mProgressStatus++;         //进度+1
                Log.d(TAG, "handleMessage mProgressStatus:" + mProgressStatus);
                Log.d(TAG, "handleMessage tid:" + android.os.Process.myTid());
                timer.setProgress(TIME - mProgressStatus);           //更新进度条的显示进度
                handler.sendEmptyMessageDelayed(TIMER_MSG, 1000);    
            } else {
                Toast.makeText(MainActivity.this, "时间到!", Toast.LENGTH_SHORT).show();       
                Log.d(TAG, "handleMessage timeout!");
            }
        }
    };
}

GitHub - hanyuhang-hz/android-demos

4 使用Handler实现轮播广告

使用Message类时注意:尽管Message类有public构造方法,但通常情况下,需要使用Message.obtain()或Handler.obtainMessage()从消息池中获得空消息对象,以节省资源。
Message对象属性描述如下:

属性

类型

描述

arg1

int

存储整型数据

arg2

int

存储整型数据

obj

Object

存储Object类型的任意对象

replyTo

Messenger

指定此Message发送到何处的Messenger

what

int

指定用户自定义的消息代码

MainActivity.java

public class MainActivity extends Activity {
    final int FLAG_MSG = 0x001;
    private ViewFlipper flipper;
    private Message message;
    //定义图片数组
    private int[] images = new int[]{R.drawable.img1, R.drawable.img2, R.drawable.img3,
            R.drawable.img4, R.drawable.img5, R.drawable.img6, R.drawable.img7, R.drawable.img8};
    private Animation[] animation = new Animation[2];  //定义动画数组,为ViewFlipper指定切换动画

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        flipper = (ViewFlipper) findViewById(R.id.viewFlipper);
        for (int i = 0; i < images.length; i++) {
            ImageView imageView = new ImageView(this);
            imageView.setImageResource(images[i]);  //将遍历的图片保存在ImageView中
            flipper.addView(imageView);             //加载图片
        }

        animation[0] = AnimationUtils.loadAnimation(this, R.anim.slide_in_right); //右侧平移进入动画
        animation[1] = AnimationUtils.loadAnimation(this, R.anim.slide_out_left); //左侧平移退出动画
        flipper.setInAnimation(animation[0]);   //为flipper设置图片进入动画效果
        flipper.setOutAnimation(animation[1]);  //为flipper设置图片退出动画效果

        message=Message.obtain();
        message.what=FLAG_MSG;
        handler.sendMessage(message);
    }
    
    Handler handler = new Handler() {  //创建android.os.Handler对象
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == FLAG_MSG) {
                flipper.showPrevious();
            }
            message=handler.obtainMessage(FLAG_MSG);   //获取要发送的消息
            handler.sendMessageDelayed(message, 3000);
        }
    };
}

GitHub - hanyuhang-hz/android-demos


 

5 使用Handler实现子线程发送处理消息

子线程中,需要手动创建一个Looper对象,并通过loop()启动Looper。

[1]调用Looper的prepare()来为当前线程创建Looper对象,同时创建MessageQueue。

[2]创建Handler实例,覆写handleMessage()方法。

[3]调用Looper的loop()方法启动Looper。

MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("Looper", "onCreate tid:" + android.os.Process.myTid());
        LooperThread thread=new LooperThread();       //创建一个线程
        thread.start();                         //开启线程
    }
}

LooperThread.java

public class LooperThread extends Thread {
    public Handler handler;
    @Override
    public void run() {
        super.run();
        Looper.prepare();              //初始化Looper对象
        //实例化一个Handler对象
        handler = new Handler() {
            public void handleMessage(Message msg) {
                Log.i("Looper", "handle msg:" + String.valueOf(msg.what));
                Log.d("Looper", "handleMessage tid:" + android.os.Process.myTid());
            }
        };

        Message m=handler.obtainMessage(); //获取一个消息
        m.what=0x7;                   //设置Message的what属性的值
        handler.sendMessage(m);          //发送消息
        Log.i("Looper", "send msg:" + String.valueOf(m.what));
        Log.d("Looper", "sendMessage tid:" + android.os.Process.myTid());
        Looper.loop();                //启动Looper
    }
}

https://github.com/hanyuhang-hz/android-demos

注意:Looper.loop()之后的代码不会被执行,因为loop()函数是一个循环。只有调用了Handler.getLooper().quit()后,loop()方法才会终止,后面的代码才会运行。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5686344.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存