美文网首页
Android学习——Handler

Android学习——Handler

作者: 鱼嘿蛮仁 | 来源:发表于2024-03-12 16:25 被阅读0次

一、概述

Handler是一套消息传递机制,通常的作用是在多线程的应用场景中。Handler机制涉及的主要组件包括Handler、Looper、Message和MessageQueue。

以下是这些组件的详细介绍:

  • Handler。消息处理者,负责发送和处理消息。
  • Message。消息的主体,包含消息的具体内容和类型。
  • MessageQueue。消息队列,用于存储和顺序分发消息。
  • Looper。消息循环器,负责从MessageQueue中取出消息并分发给Handler处理。

每个Handler对象都绑定到一个线程的Looper,这意味着它只能处理由该线程创建的消息。这种机制允许主线程(UI线程)以外的线程执行耗时操作,同时确保这些操作的结果能够安全地更新到UI上。例如,当一个线程进行网络请求或文件处理时,它可以在子线程中发送消息到Handler,然后由Handler将这些消息放入MessageQueue中,主线程(UI线程)的Looper会从MessageQueue中取出这些消息,并分发给相应的Handler对象进行处理,从而实现UI更新。

二、Handler对象创建问题

在子线程中创建Handle对象需要调用Looper.prepare()方法后,才能够创建Handler。在主线程中会自动地调用Looper.prepare()方法。

public class MainActivity extends AppCompatActivity {

    private Handler handler1;
    private Handler handler2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        handler1 = new Handler();//主线程创建Handle
        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();//子线程中创建Handle需要先调用此方法
                handler2 = new Handler();
            }
        }).start();
    }
}

三、使用方法

方式一:使用Handler.sendMessage()

在该使用方式中,因创建Handler的方式不同,又可分两种:创建Handler子类、使用匿名Handler内部类,但本质都是相同的,都是继承Handler类创建子类。

1、创建Handler子类

public class MainActivity extends AppCompatActivity {
    TextView mTxtShowTest;
    Button mBtn1, mBtn2, mBtn3;
    // 2、在主线程中创建自定义Handler(mHandler)的实例
    private mHandler mhandler = new mHandler();
     
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
     
        mTxtShowTest = (TextView) findViewById(R.id.mTxtShowTest);
        mBtn1 = (Button) findViewById(R.id.mBtn1); 
     
        mBtn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                    // 3、创建所需消息对象
                        Message msg = Message.obtain();
                        msg.what = 1;
     
                        //4、发送消息
                        mhandler.sendMessage(msg);
                    }
                    // 5、开启线程
                }).start();
            }
        }); 
    }
     
    //1、自定义Handler子类,继承Handler,重写handleMessage()方法
    class mHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //执行的UI操作
            mTxtShowTest.setText("新建Handler子类方法");
        }
    }
}

2、使用匿名Handler子类

public class MainActivity extends AppCompatActivity {
    TextView mTxtShowTest;
    Button mBtn1, mBtn2, mBtn3;
    //1、在主线程中通过匿名内部类创建Handler类对象
    private Handler mhandler2 =  new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //执行的UI操作
            mTxtShowTest.setText("匿名内部类方法");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
     
        mTxtShowTest = (TextView) findViewById(R.id.mTxtShowTest); 
        mBtn2 = (Button) findViewById(R.id.mBtn2);  
     
        mBtn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                     // 2、创建所需消息对象
                        Message msg = Message.obtain();
                        msg.what = 1;
     
                        //3、发送消息
                        mhandler2.sendMessage(msg);
                    }
                //4、开启线程
                }).start();
            }
        }); 
    } 
}
方式二、使用Handler.post()方法
public class MainActivity extends AppCompatActivity {
    TextView mTxtShowTest;
    Button mBtn1, mBtn2, mBtn3;
    //1、在主线程中创建Handler的实例 
    private Handler mhandlerPost = new Handler(); 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        mTxtShowTest = (TextView) findViewById(R.id.mTxtShowTest); 
        mBtn3 = (Button) findViewById(R.id.mBtn3); 
 
        mBtn3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //2、在子线程中使用Handler.post()
                        mhandlerPost.post(new Runnable() {
                            @Override
                            public void run() {
                //执行的UI操作
                                mTxtShowTest.setText("post方法");
                            }
                        });
                    }
                //4、开启线程
                }).start();
           }
        });  
    } 
}

四、Handler内存泄漏

在Java中,非静态内部类会持有一个外部类的隐式引用,可能会造成外部类无法被GC;

比如这里的Handler,就是非静态内部类,它会持有Activity的引用从而导致Activity无法正常释放。

而单单使用静态内部类,Handler就不能调用Activity里的非静态方法了,所以加上「弱引用」持有外部Activity。

private static class MyHandler extends Handler {
    //创建一个弱引用持有外部类的对象
    private final WeakReference<MainActivity> content;

    private MyHandler(MainActivity content) {
        this.content = new WeakReference<MainActivity>(content);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        MainActivity activity= content.get();
        if (activity != null) {
            switch (msg.what) {
                case 0: {
                    activity.notifyUI();
                }
            }
        }
    }
}

转换成Kotlin:(Tips:Kotlin 中的内部类,默认是静态内部类,使用inner修饰才为非静态~)

private class MyHandler(content: MainActivity) : Handler() {
    //创建一个弱引用持有外部类的对象
    private val content: WeakReference<MainActivity> = WeakReference(content)

    override fun handleMessage(msg: Message) {
        super.handleMessage(msg)
        val activity = content.get()
        if (activity != null) {
            when (msg.what) {
                0 -> {
                    activity.notifyUI()
                }
            }
        }
    }
}

相关文章

网友评论

      本文标题:Android学习——Handler

      本文链接:https://www.haomeiwen.com/subject/trpmzdtx.html