1.HandlerThread
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {
}
@Override
public void run() {
// 獲取線程 id
mTid = Process.myTid();
//構建一個 Looper
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
//設置線程優(yōu)先級
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
// Looper 循環(huán)
mTid = -1;
}
// 獲取當前線程的 Looper,
public Looper getLooper() {
if (!isAlive()) {
return null;
}
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
/**
* @return a shared {@link Handler} associated with this thread
* @hide 方法隱藏掉炼吴,無法調用
*/
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
//線程退出方法期丰,主要是調用 Looper.quit() 方法,不然一直在循環(huán)
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
//同上沸伏,不過這個方法會把消息隊列中的已有消息處理完才會安全地退出
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
public int getThreadId() {
return mTid;
}
}
1.HandlerThread 運行 start() 方法须尚,回調 run() 方法。
2.在 run() 方法中通過 Looper.prepare() 來創(chuàng)建消息隊列假消,并通過 Looper.looper() 方法來開啟消息循環(huán)柠并。
3.由于 Loop.loop() 是一個死循環(huán),導致 run() 也是無線循環(huán)富拗,因此當我們不需要使用 HandlerThread 的時候臼予,要調用它的 quit() 方法或者 quiteSafely() 方法。
一般用法就是用來獲取一個異步的Lopper媒峡,從而創(chuàng)建一個異步線程的Handler
public class HandlerThreadActivity extends BaseActivity {
private static final String TAG = "HandlerThreadActivity";
private Button mStartBtn;
private Handler mHandler;
private HandlerThread mHandlerThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_thread);
mStartBtn = findViewById(R.id.start_btn);
mHandlerThread = new HandlerThread("THREAD_NAME");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
mStartBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mHandler.post(new Runnable() {
@Override
public void run() {
Log.d(TAG, Thread.currentThread().getId() + " " + String.valueOf((Looper.myLooper() == Looper.getMainLooper())) + " 任務:" + this.hashCode());
SystemClock.sleep(3000);
}
});
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandlerThread.quit();
}
}
輸出日志:
2. IntentService
package android.app;
import android.annotation.WorkerThread;
import android.annotation.Nullable;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public IntentService(String name) {
super();
mName = name;
}
/**
* Sets intent redelivery preferences. Usually called from the constructor
*/
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
//注意這里瘟栖,創(chuàng)建了一個HandlerThread,也就是創(chuàng)建了一個異步線程的Looper
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
//創(chuàng)建處理異步線程任務的Handler
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
/**
* 每次啟動都會發(fā)送一個msg
*/
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
/**
* Unless you provide binding for your service, you don't need to implement this
*/
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
/**
*/
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
一般用法是繼承IntentService,然后把要做的業(yè)務邏輯重寫在OnHandlerIntent()方法里谅阿,這個方法是運行在異步線程的,每次啟動一下該服務酬滤,執(zhí)行完后會自己銷毀签餐。例:
package com.bourne.android_common.ServiceDemo;
import android.app.IntentService;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import com.bourne.common_library.utils.Logout;
public class MyIntentService extends IntentService {
/**
* 是否正在運行
*/
private boolean isRunning;
/**
*進度
*/
private int count;
/**
* 廣播
*/
private LocalBroadcastManager mLocalBroadcastManager;
public MyIntentService() {
super("MyIntentService");
Logout.e("MyIntentService");
}
@Override
public void onCreate() {
super.onCreate();
Logout.e("onCreate");
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
}
@Override
protected void onHandleIntent(Intent intent) {
Logout.e("onHandleIntent");
try {
Thread.sleep(1000);
isRunning = true;
count = 0;
while (isRunning) {
count++;
if (count >= 100) {
isRunning = false;
}
Thread.sleep(50);
sendThreadStatus("線程運行中...", count);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 發(fā)送進度消息
*/
private void sendThreadStatus(String status, int progress) {
Intent intent = new Intent(IntentServiceActivity.ACTION_TYPE_THREAD);
intent.putExtra("status", status);
intent.putExtra("progress", progress);
mLocalBroadcastManager.sendBroadcast(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Logout.e("線程結束運行..." + count);
}
}
創(chuàng)建個Activity:
package com.bourne.android_common.ServiceDemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.bourne.android_common.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class IntentServiceActivity extends AppCompatActivity {
/**
* 狀態(tài)文字
*/
@BindView(R.id.tv_status)
TextView tv_status;
/**
* 進度文字
*/
@BindView(R.id.tv_progress)
TextView tv_progress;
/**
* 進度條
*/
@BindView(R.id.progressbar)
ProgressBar progressbar;
private LocalBroadcastManager mLocalBroadcastManager;
private MyBroadcastReceiver mBroadcastReceiver;
public final static String ACTION_TYPE_THREAD = "action.type.thread";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_service);
ButterKnife.bind(this);
//注冊廣播
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
mBroadcastReceiver = new MyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_TYPE_THREAD);
mLocalBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);
initView();
}
public void initView() {
tv_status.setText("線程狀態(tài):未運行");
progressbar.setMax(100);
progressbar.setProgress(0);
tv_progress.setText("0%");
}
@Override
protected void onDestroy() {
super.onDestroy();
//注銷廣播
mLocalBroadcastManager.unregisterReceiver(mBroadcastReceiver);
}
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case ACTION_TYPE_THREAD:
//更改UI
int progress = intent.getIntExtra("progress", 0);
tv_status.setText("線程狀態(tài):" + intent.getStringExtra("status"));
progressbar.setProgress(progress);
tv_progress.setText(progress + "%");
if (progress >= 100) {
tv_status.setText("線程結束");
}
break;
}
}
}
@OnClick({R.id.btn_start})
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_start:
Intent intent = new Intent(IntentServiceActivity.this, MyIntentService.class);
startService(intent);
break;
}
}
}
沒什么高深的東西,但是沒看過源碼可能不知道他的用法盯串,不少面試官會拿來問氯檐,用來檢測你對安卓api的熟悉程度。