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;
      }
  }
}

注意:記得添加網絡權限!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM