Handler简述和实例

Handler

1、简介:

Android中主线程是不能进行耗时操作的,子线程是不能进行更新UI的。所以就有了handler,它的作用就是实现线程之间的通信。 handler整个流程中,主要有四个对象,handler,Message,MessageQueue,Looper。当应用创建的时候,就会在主线程中创建handler对象, 我们通过要传送的消息保存到Message中,handler。post,handler通过调用sendMessage方法将Message发送到MessageQueue中,Looper对象就会不断的调用loop()方法 不断的从MessageQueue中取出Message交给handler进行处理。从而实现线程之间的通信。

2、Looper、MessageQueue、Message、Handler的关系

Looper:

每一个线程只有一个Looper,每个线程在初始化Looper之后,然后Looper会维护好该线程的消息队列,用来存放Handler发送的Message,并处理消息队列出队的Message。它的特点是它跟它的线程是绑定的,处理消息也是在Looper所在的线程去处理,所以当我们在主线程创建Handler时,它就会跟主线程唯一的Looper绑定,从而我们使用Handler在子线程发消息时,最终也是在主线程处理,达到了异步的效果。

在主线程中,ActivityThread默认会把Looper初始化好,prepare以后,当前线程就会变成一个Looper线程。

MessageQueue:

MessageQueue是一个消息队列,用来存放Handler发送的消息。每个线程最多只有一个MessageQueue。MessageQueue通常都是由Looper来管理,而主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个MessageQueue。其他非主线程,不会自动创建Looper。

Message:

消息对象,就是MessageQueue里面存放的对象,一个MessageQueu可以包括多个Message。当我们需要发送一个Message时,我们一般不建议使用new Message()的形式来创建,更推荐使用Message.obtain()来获取Message实例,因为在Message类里面定义了一个消息池,当消息池里存在未使用的消息时,便返回,如果没有未使用的消息,则通过new的方式创建返回,所以使用Message.obtain()的方式来获取实例可以大大减少当有大量Message对象而产生的垃圾回收问题。

Handler的主要用途

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

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

实例一:通过Handler配合Message或者Runnable实现倒计时

public class MainActivity extends AppCompatActivity {
   private static final int UPDATE = 0x1;
   private TextView mTv;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       mTv = findViewById(R.id.tv);
       begin();
  }

   private Handler mHandler = new Handler(){
       @Override
       public void handleMessage(@NonNull Message msg) {
           switch (msg.what){
               case UPDATE:
                   mTv.setText(String.valueOf(msg.arg1));
                   break;
          }
      }
  };

   public void begin(){
       new Thread(new Runnable() {
           @Override
           public void run() {
               for (int i=5;i>0;i--){
                   Message msg = new Message();
                   msg.what = UPDATE;
                   msg.arg1 = i;
                   mHandler.sendMessage(msg);
                   try {
                       Thread.sleep(1000);
                  }catch (InterruptedException e){
                       e.printStackTrace();
                  }
                   Log.d("xxxxx", "run: ");
              }
               startActivity(new Intent(MainActivity.this,Main2Activity.class));
               finish();
          }
      }).start();
  }

   @Override
   protected void onDestroy() {
       super.onDestroy();
       Log.d("xxxxx", "onDestroy: ");
  }
  }

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

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

public class Main2Activity extends AppCompatActivity implements View.OnClickListener {
   private Button mLoad;
   private Button mReset;
   private ImageView mImageView;

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

       mLoad = findViewById(R.id.load);
       mLoad.setOnClickListener(this);
       mReset = findViewById(R.id.reset);
       mReset.setOnClickListener(this);
       mImageView = findViewById(R.id.img_show);
  }

   public Bitmap loadPic(){
       Bitmap bitmap = null;
       int respondCode = 0;
       InputStream inputStream = 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){
               inputStream = connection.getInputStream();
               bitmap = BitmapFactory.decodeStream(inputStream);
          }
      }catch (MalformedURLException e){
           e.printStackTrace();
           Toast.makeText(this,"访问失败",Toast.LENGTH_SHORT).show();
      } catch (ProtocolException e) {
           e.printStackTrace();
      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           if (inputStream != null){
               try {
                   inputStream.close();
              }catch (IOException e){
                   e.printStackTrace();
              }
          }
      }
       return bitmap;
  }

   @Override
   public void onClick(View v) {
       int i = v.getId();
       switch (i){
           case R.id.load:
               new Thread(new Runnable() {
                   @Override
                   public void run() {
                       final Bitmap bitmap = loadPic();
                       Handler handler = new Handler(Looper.getMainLooper());
                       handler.post(new Runnable() {
                           @Override
                           public void run() {
                               mImageView.setImageBitmap(bitmap);
                          }
                      });
                  }
              }).start();
               break;
           case R.id.reset:
               mImageView.setImageBitmap(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_foreground));
               break;
      }
  }
}

注意:记得添加网络权限!

原文地址:https://www.cnblogs.com/littleboy123/p/13036264.html