android開發筆記(一)消息機制

本文章是學習尚硅谷android系列視頻中的《消息機制與異步任務》章節所記載的筆記。

 

Message:消息

  • 可理解爲線程間通訊的數據單元,可通過message攜帶需要的數據
  • 創建對象:Message.obtain(what)
  • 封裝數據:

public int what  //id標識

public int arg1

public int arg2

public Object obj

Handler:處理器

  • Handler是Message的處理器,同時也負責消息的發送和移除工作
  • 發送即時消息:sendMessage(Message msg)
  • 發送延時消息:sendMessageDelayed(Message msg,long time)(實際是延時處理不是延時發送)
  • 處理消息:handleMessage(Message msg)(回調方法)
  • 移除還未處理的消息:removeMessages(int what)

MessageQueue:消息隊列

  • 用來存放通過Handler發送的消息
  • 它是一個按Message的when排序的優先級隊列

Looper(鉤子):循環器

  • 負責循環取出MessageQueue裏面的當前需要處理的Message
  • 交給對應的Handler進行處理
  • 處理完後,將Message緩存到消息池中,以備複用

Handler的基本使用步驟:

  1. 創建Handler成員變量對象,並重寫handleMessage(Message msg)方法
  2. 在分/主線程創建Message對象
  3. 使用Handler對象發送Message
  4. 在handleMessage(Message msg)中處理消息
activity代碼:

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.HashMap;

public class MainActivity extends AppCompatActivity {
    private String address = "https://www.sojson.com/open/api/weather/json.shtml?";
    ProgressDialog progressDialog;
    private Button button;
    private TextView textView;

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

    private void initViews(){
        progressDialog = new ProgressDialog(this);
        progressDialog.setTitle("加載中...");
        progressDialog.setCancelable(true);
        textView = findViewById(R.id.textView);
        button = findViewById(R.id.button);
        button.setOnClickListener(onClickListener);
    }

    View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.button:
                    getWeather();
                    break;
            }
        }
    };

    @SuppressLint("HandlerLeak")
    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            if(progressDialog != null && progressDialog.isShowing()){
                progressDialog.dismiss();
            }
            textView.setText(msg.getData().getString("weather"));
        }
    };


    private void getWeather(){
        progressDialog.show();
        new Thread(new Runnable() {
            @Override
            public void run() {
                HashMap<String,String> map = new HashMap<>();
                map.put("city","成都");
                String result = HttpNetTool.requestGet(map,address);
                Message message = Message.obtain(handler,1);
                Bundle bundle = new Bundle();
                bundle.putString("weather",result);
                message.setData(bundle);
                handler.sendMessage(message);
            }
        }).start();
    }
}





xml代碼:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="TextView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="獲取天氣"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

權限:

    <uses-permission android:name="android.permission.INTERNET"/>

Handler的小DEMO:

Activity代碼:

package com.atguigu.l05_handler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

/**
 * 使用Handler的小DEMO
 * @author 張曉飛
1. 手動增加/減少
2. 自動增加/減少
3. 限制數字的最大和最小值 [1,20]
4. 限制Button可操作性
 */
public class HandlerDemoActivity extends Activity implements OnClickListener {

	private static final int WHAT_INCREASE = 1;
	private static final int WHAT_DECREASE = 2;
	
	
	private TextView tv_demo_number;
	private Button btn_demo_increase;
	private Button btn_demo_decrease;
	private Button btn_demo_pause;
	
	private Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			//得到當前顯示的數值
			int number = Integer.parseInt(tv_demo_number.getText().toString());
			switch (msg.what) {
			case WHAT_INCREASE:
				//限制number<=20
				if(number==20) {
					//設置暫停不能操作
					btn_demo_pause.setEnabled(false);
					Toast.makeText(HandlerDemoActivity.this, "已經達到最大值", 0).show();
					return;
				}
				
				number++;
				tv_demo_number.setText(number+"");
				//發送增加的延遲消息
				handler.sendEmptyMessageDelayed(WHAT_INCREASE, 1000);
				break;
			case WHAT_DECREASE:
				//限制number>=1
				if(number==1) {
					//設置暫停不能操作
					btn_demo_pause.setEnabled(false);
					Toast.makeText(HandlerDemoActivity.this, "已經達到最小值", 0).show();
					return;
				}
				number--;
				tv_demo_number.setText(number+"");
				//發送減少的延遲消息
				handler.sendEmptyMessageDelayed(WHAT_DECREASE, 1000);
				break;
			default:
				break;
			}
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_handler_demo);
		init();
	}

	private void init() {
		tv_demo_number = (TextView) findViewById(R.id.tv_demo_number);
		btn_demo_increase = (Button) findViewById(R.id.btn_demo_increase);
		btn_demo_decrease = (Button) findViewById(R.id.btn_demo_decrease);
		btn_demo_pause = (Button) findViewById(R.id.btn_demo_pause);
		
		btn_demo_increase.setOnClickListener(this);
		btn_demo_decrease.setOnClickListener(this);
		btn_demo_pause.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		if(v==btn_demo_increase) {//自動增加  what =1
			//限制Button可操作性
			btn_demo_increase.setEnabled(false);
			btn_demo_decrease.setEnabled(true);
			btn_demo_pause.setEnabled(true);
			
			//停止減少(移除未處理的減少的消息)
			handler.removeMessages(WHAT_DECREASE);
			//發消息(增加)
			handler.sendEmptyMessage(WHAT_INCREASE);
		} else if(v==btn_demo_decrease) {//自動減少 what=2
			//限制Button可操作性
			btn_demo_increase.setEnabled(true);
			btn_demo_decrease.setEnabled(false);
			btn_demo_pause.setEnabled(true);
			
			//停止增加(移除未處理的增加的消息)
			handler.removeMessages(WHAT_INCREASE);
			
			//發消息(減少)
			handler.sendEmptyMessage(WHAT_DECREASE);
		} else if(v==btn_demo_pause) {//暫停
			
			//限制Button可操作性
			btn_demo_increase.setEnabled(true);
			btn_demo_decrease.setEnabled(true);
			btn_demo_pause.setEnabled(false);
			
			//停止增加/減少(移除未處理的減少/增加的消息)
			handler.removeMessages(WHAT_INCREASE);
			handler.removeMessages(WHAT_DECREASE);
		}
	}
}

XML代碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv_demo_number"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="10"
        android:textColor="#ff0000" 
        android:textSize="20sp"/>

    <Button
        android:id="@+id/btn_demo_increase"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="自動增加" />

    <Button
        android:id="@+id/btn_demo_decrease"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="自動減少" />

    <Button
        android:id="@+id/btn_demo_pause"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="暫停" 
        android:enabled="false"/>

</LinearLayout>

Handler原理:

 

源碼簡單解析:

Message:

屬性:

  • public int what;//標識(id)
  • public int arg1;//保存int數據
  • public int arg2;//保存int數據
  • public Object obj;//保存任意數據
  • long when;//記錄應該被處理的時間值
  • Handler target;//處理message的handler的引用,也就是發消息的handler
  • Runnable callback;//用來處理消息的回調器
  • Message next;//指向下一個Message,用來形成一個鏈表
  • private static Message sPool;//用來緩存處理過的Message對象,以便複用

方法:

  • public static Message obtain();//它利用了Message中的消息池(sPool) 

Handler:

方法:

  • sendMessage(Message msg);//發送即時消息
  • sendMessageDelayed(Message msg,long delayMillis);//發送延時消息
  • sendEmptyMessage(int what);//發送即時得空消息
  • sendEmptyMessageDelayed(int what,long delayMillis);//發送空的延時消息
  • sendMessageAtTime(Message msg,long uptimeMillis);//
  • removeMessages(int what);//移除還未處理的消息
  • handleMessage(Message msg);//處理消息的回調

MessageQueue:

方法:

  • enqueueMessage(Message msg,long when);//將Message添加到隊列中,根據when來排序

Looper:

方法:

  • loop();//核心方法

final Looper me = myLooper();//得到Looper對象

final MessageQueue queue = me.mQueue;//得到消息對列對象

for(;;){

                    Message  msg = queue.next();//可能處於等待狀態,但是不會阻塞主線程

                    ......

                    msg.target.dispatchMessage(msg);//調用Handler去分發消息,並處理消息

                    msg.recycle();//回收message

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章