Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中的多線程編程(二)Handler的原理(附源碼)

Android中的多線程編程(二)Handler的原理(附源碼)

編輯:關於Android編程

Android中Handler的原理

一.Handler的原理:

1.Handler、Looper、MessageQueue之間的關系。

(1).Handler類:向MessageQueue消息隊列中發送消息,接收Looper返回來的消息並處理。

(2).Looper類: 存儲消息隊列的容器。負責接收Handler發送的消息,並直接把消息回傳給Handler自己。

(3).MessageQueue類:存儲消息。

2.關系:

(1).創建Handler對象的時候,它就會綁定到默認的線程(UI線程)中,這個線程中就會有一個消息隊列。

private Handler mHandler = new Handler() {
    public void handleMessage(android.os.Message msg) {
        Log.d(TAG, 主線程 Thread UI: + Thread.currentThread().getId());
        mView.setText(111);
    };
}; 

(2).如果是新開啟一個子線程,在該線程中操作Handler的時候,就要自己創建一個Looper對象,從而找到相應的消息隊列。也就是說Handle和Looper是相互關聯的。

package com.chengdong.su.handlerdemo;

import android.app.Activity;
import android.app.ActionBar;
import android.app.Fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.os.Build;

/**
 * 
 * @author scd
 * 
 */
public class ThridActivity extends Activity {
    private String TAG = getClass().getSimpleName();
    private TextView mView;
    private MyThread mThread;
    /**
     * 創建一個默認的Handler
     */
    private Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            Log.d(TAG, -------UI Thread: + Thread.currentThread().getId());
            mView.setText(你好);
        };

    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        mThread = new MyThread();
        mThread.start();
        try {
            mThread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 子線程
        mThread.myHandler.sendEmptyMessage(0);
        // 主線程
        mHandler.sendEmptyMessage(1);
    }

    private void init() {
        mView = (TextView) findViewById(R.id.textView1);
    }

    /**
     * 自定義的Thread
     * 
     * @author scd
     * 
     */
    public class MyThread extends Thread {
        public Handler myHandler;

        @Override
        public void run() {
            Looper.prepare();
            myHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Log.d(TAG, ------>Thread:
                            + Thread.currentThread().getId());
                    System.out.println(---子線程----);

                }
            };
            // 循環處理消息
            Looper.loop();

        }

    }

}

但是使用以上的方式會出現多線程並發導致的空指針問題,為了避免這個問題,谷歌給我們封裝了一個很好用的類:HandlerThread類。

3.HandlerThread類:

(1).解決多線程並發導致的空指針問題。
HandlerThread的使用代碼如下:

package com.chengdong.su.handlerdemo;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;

/**
 * 
 * @author scd
 * 
 */
public class FourActivity extends Activity {
    private String TAG = getClass().getSimpleName();
    private String mName = HandlerThread;
    private HandlerThread mThread;
    private Handler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 封裝類
        mThread = new HandlerThread(mName);
        // 開啟線程
        mThread.start();
        // 方式一:Handler是在子線程
        mHandler = new Handler(mThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.d(TAG, ---子線程----HandlerThread :
                        + Thread.currentThread().getId());

            }
        };
        // 方式二:Handler是在主線程
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.d(TAG, ---主線程 UI----HandlerThread :
                        + Thread.currentThread().getId());

            }
        };
        mHandler.sendEmptyMessage(0);
        Log.d(TAG, ---主線程----UIThread : + Thread.currentThread().getId());

    }
}       

注:方式一中的mHandler是運行在子線程中的,可以在該Handler中處理耗時的異步任務,發送消息,處理消息等。

(2).Android中主線程和子線程之間的通信:

A:子線程發送給主線程消息:讓主線程更新UI界面
B:主線程發送給子線程消息:讓子線程做相應的邏輯處理。
代碼如下:

package com.chengdong.su.handlerdemo;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

/**
 * 主線程和子線程之間進行互相的發送消息,進行通信
 * 
 * @author scd
 * 
 */
public class FiveActivity extends Activity implements OnClickListener {
    private String TAG = getClass().getSimpleName();
    private String mName = HandlerThread;
    // 初始化主線程的Handler
    private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            Message message = new Message();
            // 主線程發送給子線程消息
            mThreadHandler.sendMessageDelayed(message, 1000);
            Log.d(TAG, -------->主線程發送給子線程消息);

        };
    };
    // 子線程對象
    private HandlerThread mThread;
    // 子線程的Handler
    private Handler mThreadHandler;

    private Button mButton1;
    private Button mButton2;

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

    /**
     * init the View
     */
    private void init() {
        mButton1 = (Button) findViewById(R.id.button1);
        mButton2 = (Button) findViewById(R.id.button2);
        mButton1.setOnClickListener(this);
        mButton2.setOnClickListener(this);
        // 初始化子線程的Handler
        mThread = new HandlerThread(mName);
        mThread.start();
        // 初始化子線程中的Handler
        mThreadHandler = new Handler(mThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                Message message = new Message();
                mHandler.sendMessageDelayed(message, 1000);
                Log.d(TAG, -------->子線程發送給主線程消息);

            }
        };
        Log.d(TAG, ------->init主線程);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.button1: {
            // 主線程發送消息
            mHandler.sendEmptyMessage(0);

            break;
        }
        case R.id.button2: {
            // 取消消息
            mHandler.removeMessages(0);

            break;
        }

        default:
            break;
        }

    }

}

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved