Android学习——Handler

Handler

1.Handler介绍

在Android开发中,我们常常会使用单独的线程来完成某些操作,比如用一个线程来完成从网络上下载图片,然后显示在ImageView上,在多线程操作时,Android中必须保证以下两点:

  • 不要阻塞UI线程
  • 不要在UI线程之外访问Android UI工具包

有了以上两点限制,我们在线程之间的消息如何进行传递?Handler(消息的处理者)

package com.example.handler;

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.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView=findViewById(R.id.textView);
    }

    //重写handler方法
    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 100://下载完成后,更行UI状态
                    textView.setText("下载完成");
                    break;
            }
        }
    };

    public void downloadClick(View v){
        //使用线程模拟下载操作
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    break;
                }
                //简写
                handler.sendEmptyMessage(100);//发送一个空消息,标记为100
                //全写
//                Message msg=handler.obtainMessage();//获取一个消息对象
//                msg.what=100;
//                msg.obj="要存储的信息";//任意类型
//                handler.sendMessage(msg);//发送消息
            }
        }).start();
    }
}

在这里插入图片描述在这里插入图片描述
发送消息的方法:

//在指定时间后发送消息
handler.sendEmptyMessageAtTime(200,System.currentTimeMillis()+3000);
//延迟多少时间后发送消息
handler.sendEmptyMessageDelayed(300,2000);

2.Handler常用API

使用Handler可以完成以下两点工作:

  • 消息调度和将来的某个时间点执行一个Runnable
  • 多个任务加入到一个队列中执行

Handler相关方法

void handlerMessage(Message msg):Subclasses must implement this to recive messages.
final Looper getLooper()
final Message obtainMessage()
final Message obtainMessage(int what)
final Message obtainMessage(int what,Object obj)
final boolean post(Runnable r)
final boolean postAtTime(Runnable r,long uptimeMillis)
final boolean postDelayed(Runnable r,long delayMillis)

3.Handler内部实现原理

Handler实现机制:

  • Message对象,表示要传递的一个消息,内部使用链表数据结构实现一个消息池,用于重复利用,避免大量创建消息对象,造成浪费。
  • Handler对象(消息处理者),负责把消息存入到消息队列中,以及接受Looper从消息队列中取出的消息,通过handlerMessage方法处理消息。
  • MessageQueue对象,存放消息对象的消息队列,先进先出原则。
  • Looper对象(消息队列处理者),负责管理当前线程的消息队列(MessageQueue),用于循环检查消息队列,从消息队列中一个一个的取出消息对象,传入handlerMessage方法。

Android启动程序时会在UI线程创建一个MessageQueue

在这里插入图片描述

4.Handler内存泄露问题分析

Handler内存泄露问题:activity虽然退出,但是Handler依然获取到activity的引用,导致activity没有完全退出,还是占用内存,导致内存泄露。

正确的Handler使用方法

package com.example.handler;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.lang.ref.WeakReference;

/*
 * handler的内存泄露问题
 * 1.定义一个内部类时,会默认拥有外部类对象的引用,所以建议使用内部类时,最好定义为一个静态内部类。
 * 2.引用的强弱 强引用->软引用->弱引用
 * */
public class HandlerMemoryActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_memory);
        //使用handler延迟执行一个Runnable(10分钟)
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable");
            }
        },1000*60*10);
        finish();//关闭当前Activity
    }

    private MyHandler handler=new MyHandler(this);

    //标准的Handler写法
    private static class MyHandler extends Handler{
        WeakReference<HandlerMemoryActivity> weakReference;
        public MyHandler(HandlerMemoryActivity activity){
            weakReference=new WeakReference<HandlerMemoryActivity>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            HandlerMemoryActivity activity=weakReference.get();
            if (activity!=null){

            }
        }
    }
}

5.使用Handler实现APP的闪屏页

闪屏页的作用

  • 欢迎界面
  • 初始化工作

设置闪屏页背景图片

<ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/hf"
        android:scaleType="centerCrop"/>

清单文件中设置全屏

android:theme="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen"

实现闪屏页功能

package com.example.handler;

import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.lang.ref.WeakReference;

public class SplashActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                startMainActivity();
            }
        },3000);
    }
    private void startMainActivity(){
        Intent intent=new Intent(this,MainActivity.class);
        startActivity(intent);
    }

    private Handler handler=new Handler();

//    private final MyHandler handler=new MyHandler(this);
//
//    private static class MyHandler extends Handler{
//        private WeakReference<SplashActivity> weakReference;
//        public MyHandler(SplashActivity activity){
//            weakReference=new WeakReference<SplashActivity>(activity);
//        }
//        @Override
//        public void handleMessage(Message msg) {
//            super.handleMessage(msg);
//        }
//    }
}

在这里插入图片描述在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/UUUUUltraman/article/details/89087445
今日推荐