什么是Handler

Posted lixiansheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是Handler相关的知识,希望对你有一定的参考价值。

定义

Handler是用来结合线程的消息队列来发送、处理"Message对象"和"Runnable对象"的工具。

每一个Handler实例之后会关联一个线程和该线程的消息队列。也就是说,当你创建一个Handler的时候,从此开始,他就会自动关联到所在的线程/消息队列,然后它就会陆续把Message/Runnable分发到消息队列,并在他们出队的时候处理掉。因为android只允许在主线程中更新UI,Handler的目的就是作为线程通信的桥梁,进而再通过主线程更新UI。使用Handler这种异步回调机制,使我们可以再完成一个很长的任务后再做出相应的通知。

Handler和Message、MessageQueue、Looper之间的关系

Message

Handler接收与处理的消息对象

MessageQueue

消息队列,以先进先出队列形式管理所有的Message,且在初始化Looper对象时会创建一个与之关联的MessageQueue。每个线程最多只有一个MessageQueue。MessageQueue通常都是由Looper来管理,而主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个MessageQueue。其他非主线程,不会自动创建Looper。

Looper

每个线程只能够一个Looper,管理MessageQueue,不断从中去除Message分发给对应的Handler处理。

通俗一点讲:当我们的子线程想修改Activity中的UI组件时,我们可以新建一个Handler对象,通过这个对象向主线程发送消息;而我们发送的消息会先到主线程的MessageQueue中进行等待,由Looper按先入先出顺序取出,再根据Message对象的what属性分发给对应的Handler进行处理。

技术图片

Handler的主要用途

1.推送未来某个时间点将要执行的Message或者Runnable到消息队列

 

通过Handler+Message的方式更新UI

 

public class MainActivity extends AppCompatActivity 

    private TextView text;

    private static final int UPDATE_TEXT = 1;  //整型常量用于表示更新TextView这个动作

    @Override
    protected void onCreate(Bundle savedInstanceState)
        super.onCreate(savedInstanceState);
        setContentView(R.id.activity_main);
        text = (TextView) findViewById(R.id.text); 
        Button chaneText = (Button) findViewById(R.id.change_text);
        change_text.setOnClickListener(this);
    

    //新增Handler对象,并重写父类的handlerMessage()方法,在这里对具体的Message进行处理
    private Handler handler = new Handler()  
        public void handleMessage(Message msg)  //收到消息,在HandleMessage()方法中对消息进行处理
            switch (msg.what)
                case UPDATE_TEXT:
                // 在这里进行UI操作,处于主线程中
                    text.setText("Nice to meet you");
                    break;
                default:
                    break;
            
        
    ;

    @Override
    public void onClick(View v)
        switch(v.getId())
            case R.id.change_text:
                new Thread(new Runnable()
                    @Override
                    public void run()
                        Message message = new Message();
                        message.what = UPDATE_TEXT;    //将waht字段的值指定为UPDATE_TEXT
                        handler.sendMessage(message);    //调用Handler的sendMessage()方法发送消息
                    
                ).start();
                break;
            default:
                break;
        
    

 

 

 

2.在子线程把需要在另一个线程执行的操作加入到消息队列中去

通过Handler + Message来实现子线程加载图片,在UI线程显示图片

public class ThreadActivity extends AppCompatActivity implements View.OnClickListener 
    private ActivityThreadBinding mBinding = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_thread);
        // 设置点击事件
        mBinding.clickBtn.setOnClickListener(this);
        mBinding.resetBtn.setOnClickListener(this);
    

    @Override
    public void onClick(View v) 
        switch (v.getId()) 
            // 响应load按钮
            case R.id.clickBtn:
                // 开启一个线程
                new Thread(new Runnable() 
                    @Override
                    public void run() 
                        // 在Runnable中进行网络读取操作,返回bitmap
                        final Bitmap bitmap = loadPicFromInternet();
                        // 在子线程中实例化Handler同样是可以的,只要在构造函数的参数中传入主线程的Looper即可
                        Handler handler = new Handler(Looper.getMainLooper());
                        // 通过Handler的post Runnable到UI线程的MessageQueue中去即可
                        handler.post(new Runnable() 
                            @Override
                            public void run() 
                                // 在MessageQueue出队该Runnable时进行的操作
                                mBinding.photo.setImageBitmap(bitmap);
                            
                        );
                    
                ).start();
                break;
            case R.id.resetBtn:
                mBinding.photo.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.default_pic));
                break;
        
    

    /***
     * HttpUrlConnection加载图片,不多说
     * @return
     */
    public Bitmap loadPicFromInternet() 
        Bitmap bitmap = null;
        int respondCode = 0;
        InputStream is = null;
        try 
            URL url = new URL("https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1421494343,3838991329&fm=23&gp=0.jpg");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(10 * 1000);
            connection.setReadTimeout(5 * 1000);
            connection.connect();
            respondCode = connection.getResponseCode();
            if (respondCode == 200) 
                is = connection.getInputStream();
                bitmap = BitmapFactory.decodeStream(is);
            
         catch (MalformedURLException e) 
            e.printStackTrace();
            Toast.makeText(getApplicationContext(), "访问失败", Toast.LENGTH_SHORT).show();
         catch (IOException e) 
            e.printStackTrace();
         finally 
            if (is != null) 
                try 
                    is.close();
                 catch (IOException e) 
                    e.printStackTrace();
                
            
        
        return bitmap;
    

 

以上是关于什么是Handler的主要内容,如果未能解决你的问题,请参考以下文章

Android JNI之C/C++层调用JAVA

sloop公共函数之添加信号,定时器及socket

Android面试题笔记

Android JNI之C/C++层调用JAVA

不断改变android按钮颜色

Android Handler消息机制详解