1. 说说对Handler 的了解
//\frameworks\base\core\java\android\os\Handler.java
//\frameworks\base\core\java\android\os\Looper.java
//\frameworks\base\core\java\android\os\Message.java
//\frameworks\base\core\java\android\os\MessageQueue.java
-
Android Handler 是一套 异步音讯传递机制(异步通讯机制)。首要适用于同一个组件(或许说是同一个文件中)不同线程之间的信息传递。
-
有时分需求在子线程中进行耗时的 IO 操作,这可能是读取文件或许拜访网络等,当耗时操作完结今后可能需求在 UI上做一些改动,由于 Android 开发标准的约束,咱们并不能在子线程中拜访 UI 控件,不然就会触发程序反常,这个时分经过 Handler 就能够将更新 UI 的操作切换到主线程中履行。
-
Handler机制 由Handler,Message,MessageQueue和Looper四个组件组成
Message 是线程之间传递的信息,它能够在内部带着少数的信息,用于在不同线程之间交流数据;
Handler 望文生义也便是处理者的意思,它首要是用于发送和处理音讯的。发送音讯一般是运用 Handler.sendMessage()
,而宣布的音讯经过一系列地曲折处理后,终究会传递到Handler.handleMessage()
;
MessageQueue 是音讯行列的意思,它首要用于存放一切经过 Handler 发送的音讯。这部分音讯会一直存在于音讯行列中,等候被处理,其本质上是一个准时刻排序的单向链表;
Looper 是每个线程中的 MessageQueue 的管家,调用 Looper 的 loop() 办法后,就会进入到一个无限循环傍边,然后每当发现 MessageQueue 中存在一条音讯,就会将它取出,并传递到 Handler.handleMessage()
办法中。
-
Handler的运用办法
* <p>This is a typical example of the implementation of a Looper thread, * using the separation of {@link #prepare} and {@link #loop} to create an * initial Handler to communicate with the Looper. * * <pre> * class LooperThread extends Thread { * public Handler mHandler; * * public void run() { * Looper.prepare(); * * mHandler = new Handler(Looper.myLooper()) { * public void handleMessage(Message msg) { * // process incoming messages here * } * }; * * Looper.loop(); * } * }</pre> */
自己对Handler机制运用的了解:
a.
Looper.prepare()
本质是去创立Looper, 而创立Looper的核心要义便是创立一个MessageQueue。能够将Looper看成是流水线的引擎,而MessageQueue便是流水线皮带上的托盘;public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set( new Looper(quitAllowed) ); } private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed) ; mThread = Thread.currentThread(); }
b.
new Handler(Looper.myLooper())
便是告诉Handler(工人)该去处理哪条流水线的活儿,Handler.sendMessage()
便是让Handler(工人)往流水线皮带上的托盘放需求处理的零件(message),而Handler.dispatchMessage()
便是将流水线结尾的托盘上的零件(message)取出来处理;
c.Looper.loop()
便是发动流水线引擎Looper,让流水线作业起来;
a. 传送带上的零件(Message)是先进先出的。每次工人往传送带(MessageQueue)上的托盘放零件(Message)时,会考虑下哪个零件需求处理的优先级,依照需求处理的优先级排序放入到传送带MessageQueue中;
b. 每次工人(Handler)处理完零件(message)后,会将托盘搜集起来扔进托盘堆里(sPool),这个托盘堆最多能放50个,然后后边工人需求放零件运用托盘的时分,直接从这里边拿就能够了,节省时刻;
c. 当流水线皮带上的托盘里边的零件(message)还没有抵达需求处理的时刻时,Looper会中止传送,进入待机状况;
d. 一条完好的流水线只要一个引擎(Looper)和一条传送带(MessageQueue),而工人(Handler)能够有多个。工人在往传送带上放置零件(Message)的时分,会在上面添加工人(Handler)的个人信息(msg.target),然后再流水线终端处理的工人会根据这个(msg.target)将其派发给指定的工人处理(dispatchMessage(msg));
e. 当传送带上(MessageQueue)中没有零件(Message)时,引擎(Looper)不再作业进入待机状况,整个系统阻塞在准备取下一个零件的状况中(MessageQueue.next()),实际上是调用的nativePollOnce 的底层办法,一旦传送带上又有了新的零件(Message),流水线系统就会继续作业;
2. 一个线程有几个Looper?有几个messageQueue?怎么确保?
一个线程只要一个 Looper目标和一个 MessageQueue 目标。
在创立 Handler 之前,需求调用 Looper.prepare()
,该函数确保了每个线程只要一个 Looper 目标。
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
而 MessageQueue 又是在 Looper 的结构函数中创立的,确保了一个 Looper 对应一个 MessageQueue
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
3. 一个线程能够有几个handler?那怎么确保message能分配给正确的handler 处理呢?
由于Handler能够在Activity里new,在Service里边也能够new,而Activity全部都跑在了主线程里边,这就证明了主线程中能够有多个Handler。
Handler 在 sendMessageAtTime()
时,会把本身填入 msg.target
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
然后在 Looper.loop()
不断从 MessageQueue 中获取 Message 处理的时分,会根据 msg.target 去调用对应的 dispatchMessage , 这边的 msg.target 便是前面的 handler
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
msg.recycle();
}
}
}
4. MessageQueue 的数据结构?多个线程往MessageQueue添加数据,怎么确保线程安全?
MessageQueue 是一种先进先出的数据结构,底层完结是准时排序的单向链表,当有 Message 入队时,依照 Message 的 when 值排序刺进,然后出队时则去表头的 Message;
在MessageQueue.enqueueMessage()
和MessageQueue.next()
的时分都会用到同步锁synchronized确保线程安全
final boolean enqueueMessage(Message msg, long when) {
if (msg.when != 0) {
throw new AndroidRuntimeException(msg + " This message is already in use.");
}
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
msg.when = when;
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
this.notify();
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
this.notify();
}
}
return true;
}
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
...
}
}
5. 为什么主线程能够new Handler?假如子线程想要new handler需求做哪些作业?
由于在主线程中现已提前添加了 Looper.prepareMainLooper()
和Looper.loop()
,假如子线程想要调用new handler,需求调用 Looper.prepare()
和Looper.loop()
//\frameworks\base\core\java\android\app\ActivityThread.java
public static void main(String[] args) {
...
Looper.prepareMainLooper();
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
}
public static void prepareMainLooper() {
prepare(false) ;
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
6. Handler.postDelayed() 音讯时刻精确吗?完结原理?
实际上,这个问题与线程安全性为同一个问题,多线程中线程一旦安全,时刻就不能精确;时刻一旦精确,线程就必定不安全。 由于多个线程去拜访这个行列的时分,在放入行列和取出音讯的时分都会加锁,当第一个线程还没有拜访完结的时分,第二个线程就无法运用,所以他实际的时刻会被推迟。所以,Handler所发送的Delayed音讯时刻底子精确,但不完全精确。
完结原理:postDelayed
终究会调用一个带推迟参数的 sendMessageAtTime
,然后经过MessageQueue.enqueueMessage
将带推迟时刻参数的msg依照时刻排序刺进到MessageQueue。MessageQueue是一个准时刻排序的单向链表,Looper 从 MessageQueue取msg的时分,会判别当时时刻是否抵达链表头第一个msg 的推迟时刻,假如还没到,就会经过比较推迟时刻和当时时刻计算出还需求等候的时刻,然后经过native函数nativePollOnce
进行一个阻塞等候,直到等候时刻抵达再唤醒线程履行msg;
7. MessageQueue中没有音讯的时分会发生什么?为什么Looper.loop不会阻塞主线程?
MessageQueue 行列为空时,Looper.loop()
的死循环不会退出也不会履行,而是阻塞在MessageQueue.next()
中的 nativePollOnce()
办法中,进入休眠状况,等候新音讯到来重新唤醒。这边会涉及到底层linux 的 pipe 和 epoll 机制完结。
8. 为什么Handler死循环不会卡死?
应用呈现ANR卡死和Looper的死循环其实是没有关系的。应用没有音讯需求处理的时分,它是在休眠,开释线程了;而ANR是指音讯没来得及处理,比方按键和接触事情在5s内没有处理掉,或许前台广播在10s内没有处理掉等,导致卡死;
9. IdleHandler 了解么?
IdelHandler是MessageQueue中的一个静态内部接口,当 Looper 从 MessageQueue中获取的msg为空,或许履行时刻未到时,也便是 MessageQueue空闲时就会去回调 IdleHandler.queueIdle()
。
假如 queueIdle()
回来 false,则履行完后,该idlehandler会被除掉,也便是只履行一次,假如回来true,则保留,下次MessageQueue进入空闲状况继续履行;
//\frameworks\base\core\java\android\os\MessageQueue.java
/**
* Callback interface for discovering when a thread is going to block
* waiting for more messages.
*/
public static interface IdleHandler {
/**
* Called when the message queue has run out of messages and will now
* wait for more. Return true to keep your idle handler active, false
* to have it removed. This may be called if there are still messages
* pending in the queue, but they are all scheduled to be dispatched
* after the current time.
*/
boolean queueIdle();
}
Message next() {
......
for (;;) {
......
synchronized (this) {
// 此处为正常音讯行列的处理
......
if (mQuitting) {
dispose();
return null;
}
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
//mIdleHandlers 数组,赋值给 mPendingIdleHandlers
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
pendingIdleHandlerCount = 0;
nextPollTimeoutMillis = 0;
}
}
系统源码中运用比如:ActivityThread.handleResumeActivity()
中,在 onResume 办法履行结束后,调用 Looper.myQueue().addIdleHandler(new Idler())
,去履行一些资源收回,日志打印等不那么着急的使命。除此之外,在做项目 功能优化 的时分也能够运用 IdleHandler,它在主线程空闲时履行使命,而不影响其他使命的履行。
@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
//该办法终究会履行 onResume办法
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
if (r == null) {
// We didn't actually resume the activity, so skipping any follow-up actions.
return;
}
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
}
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
if (a != null) {
mNewActivities = null;
IActivityManager am = ActivityManager.getService();
ActivityClientRecord prev;
do {
//打印一些日志
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
" finished=" +
(a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
try {
//AMS 进行一些资源的收回
am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
prev = a;
a = a.nextIdle;
prev.nextIdle = null;
} while (a != null);
}
if (stopProfiling) {
mProfiler.stopProfiling();
}
//确认Jit 能够运用,不然抛出反常
ensureJitEnabled();
return false;
}
}
10. 同步屏障了解么?
能够了解为同步屏障 是为Handler音讯机制供给的一种 优先级策略,能进步异步音讯的优先级。
Handler机制中有三种音讯:同步音讯,异步音讯和屏障音讯,咱们正常运用的音讯都是同步音讯,异步音讯能够在Handler结构时设置,也能够经过setAsynchronous
进行设置,而屏障音讯跟同步音讯的区别是target属性为null。Looper从MessageQueue中取音讯时,假如没有遇到屏障音讯,那么同步音讯和异步音讯是一样的,假如遇到屏障音讯,则会屏蔽掉该音讯之后的一切同步音讯,只履行异步音讯。
在UI制作流程中,就会运用同步屏障和异步音讯,确保在Vsync信号过来时,异步使命能被优先处理,然后让制作使命被及时履行,防止界面卡顿。
@UnsupportedAppUsage
Message next() {
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
Message msg = mMessages;
//假如msg.target为空,也便是说是一个同步屏障音讯,则进入这个判别里边
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
//在这个while循环中,找到最近的一个异步音讯
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
//找到了异步音讯
if (msg != null) {
//假如音讯的处理时刻小于当时时刻 则等候
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
//处理音讯
mBlocked = false;
//将异步音讯移除
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
//回来异步音讯
return msg;
}
} else {
// No more messages.
//没有找到异步音讯则进入阻塞状况,等候被唤醒
nextPollTimeoutMillis = -1;
}
...
}
另外需求留意的是:同步屏障不会自动移除,运用完结之后需求手动移除,不然会造成同步音讯无法处理。也便是上边提到的,经过removeSyncBarrier(int token)
办法进行移除,token便是之前添加屏障时回来的token。
public void removeSyncBarrier(int token){
}
11. Handler为什么内存走漏?怎么解决?
原因
Handler的Message被存储在MessageQueue中,有些Message并不能马上被处理,它们在MessageQueue中存在的时刻会很长,这就会导致Handler无法被收回。由于Handler是非静态的匿名内部类的实例,它会隐形的持有外部类Activity,然后导致Activity不能被收回,导致Activity走漏内存
解决办法
- 运用static 润饰的handler,运用弱引证activity目标,由于要运用activity目标中的成员(由于静态内部类不持有外部类的引证,所以运用静态的handler不会导致activity的泄露);
- 独自界说handler,同样能够弱引证activity;
- 运用内部类的handler,在onDestroy办法中removeCallbacksAndMessages;
- 还有一种办法是直接运用防止内存走漏的Handler开源库WeakHandler;
12. 怎么创立Message?为什么?
创立 Message 主张运用Message.obtain(),不要运用new message()。由于 Message 类里维护了一个 sPool 的目标,能够了解为一个 Message 链表,这个链表的默许最大长度为 50。在 Android 音讯机制中,每当一个 Message 目标被处理完结之后,就会被放入这个池中,为咱们供给了复用。当咱们调用 Message.obtain()
办法时,假如复用池中存在的 Message 目标,咱们就不会去创立一个新的 Message 目标。这样就防止频繁创立和毁掉 Message 目标带来的功能开销。减小内存的抖动和OOM。
/** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
*/
public Message() {
}
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
13. HandlerThread
Handlerthread 是承继于Thread的一个类,用于敞开一个带有looper的新线程,能够运用这个looper来创立Handler,需求留意的是必须调用start()
办法敞开线程。由于 start()
能够调用线程的 run()
办法,而 HandlerThread.run()
中会调用 Looper.prepare()
和 Looper.loop()
,然后为子线程绑定 Looper,相当于做了一层封装,便利用户运用Handler。
//frameworks\base\core\java\android\os\HandlerThread.java
/*
Handy class for starting a new thread that has a looper.
The looper can then be used to create handler classes.
Note that start() must still be called.
*/
public class HandlerThread extends Thread {
...
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();// HandlerThread在start()的时分履行run()办法,而Looper便是在这里被创立的
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
}
Handler 和 HandlerThread 的合作运用办法
HandlerThread thread1 = new HandlerThread("test1");
thread1.start();
Handler mHandler = new Handler(thread1.getLooper()){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DownloadThread.TYPE_START:
Log.e(TAG, "4.主线程知道Download线程开始下载了...这时分能够更改主界面UI");
break;
default:
break;
}
super.handleMessage(msg);
}
}
14. IntentService
IntentService 是承继于 Service 的根底类, 本质上是一个 Service。首要是用于呼应基于 Intent 的异步恳求。客户端经过 startService(Intent)
发送恳求,IntentService 接收到恳求后敞开,并在新建的子线程中按序处理异步的 Intent 恳求,在同一时刻只要一个恳求会被处理。当完结一切恳求后,IntentService 会自行封闭。
为什么官方供给了 Service 之后,又供给 IntentService呢?
Service 默许是运行在主线程的,假如咱们需求在 Service 中处理一些耗时使命,那么咱们还需求去手动的创立线程或许运用线程池去处理耗时使命(不然会呈现ANR),然后在处理完今后手动封闭Service,而 IntentService 现已帮咱们做好了这些作业,咱们只需求在 onHandleIntent
中写上耗时使命的代码,就能够在子线程中去履行,由于 onHandleIntent
是运行在子线程中的,并且在使命履行完今后,IntentService 会自己履行stopSelf(startId)
办法,自行封闭。
用 IntentService 有什么好处呢?
首要,咱们省去了在 Service 中手动开线程的麻烦,第二,当操作完结时,咱们不必手动中止 Service。
ServiceIntent 的运用比如,可参考 源码;履行效果如下图:
//\frameworks\base\core\java\android\app\IntentService.java
/**
* IntentService is an extension of the {@link Service} component class that
* handles asynchronous requests (expressed as {@link Intent}s) on demand.
* Clients send requests
* through {@link android.content.Context#startService(Intent)} calls; the
* service is started as needed, handles each Intent in turn using a worker
* thread, and stops itself when it runs out of work.
*/
@Deprecated
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
@UnsupportedAppUsage
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);
}
}
public IntentService(String name) {
super();
mName = name;
}
...
@Override
public void onCreate() {
super.onCreate();
//这边就运用到了 HandlerThread 的东西类
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
// mServiceHandler 本质是 Handler,运用了 mServiceLooper 去创立
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);
}
@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();
}
/**
* This method is invoked on the worker thread with a request to process.
* Only one Intent is processed at a time, but the processing happens on a
* worker thread that runs independently from other application logic.
* So, if this code takes a long time, it will hold up other requests to
* the same IntentService, but it will not hold up anything else.
* When all requests have been handled, the IntentService stops itself,
* so you should not call {@link #stopSelf}.
*
* @param intent The value passed to {@link
* android.content.Context#startService(Intent)}.
* This may be null if the service is being restarted after
* its process has gone away; see
* {@link android.app.Service#onStartCommand}
* for details.
*/
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
-
linux的epoll机制
- epoll机制,是一种IO多路复用机制,能够同时监控多个描述符,当某个描述符安排妥当(读或写安排妥当),则马上通知相应程序进行读或写操作,本质同步I/O,即读写是阻塞的。所以说,主线程大多数时分都是处于休眠状况,并不会耗费大量CPU资源。
/**
* A Handler allows you to send and process Message and Runnable
* objects associated with a thread's MessageQueue. Each Handler
* instance is associated with a single thread and that thread's message
* queue. When you create a new Handler it is bound to a Looper.
* It will deliver messages and runnables to that Looper's message
* queue and execute them on that Looper's thread.
*
* <p>There are two main uses for a Handler: (1) to schedule messages and
* runnables to be executed at some point in the future; and (2) to enqueue
* an action to be performed on a different thread than your own.
*
* <p>Scheduling messages is accomplished with the
* {@link #post}, {@link #postAtTime(Runnable, long)},
* {@link #postDelayed}, {@link #sendEmptyMessage},
* {@link #sendMessage}, {@link #sendMessageAtTime}, and
* {@link #sendMessageDelayed} methods. The <em>post</em> versions allow
* you to enqueue Runnable objects to be called by the message queue when
* they are received; the <em>sendMessage</em> versions allow you to enqueue
* a {@link Message} object containing a bundle of data that will be
* processed by the Handler's {@link #handleMessage} method (requiring that
* you implement a subclass of Handler).
*
* <p>When posting or sending to a Handler, you can either
* allow the item to be processed as soon as the message queue is ready
* to do so, or specify a delay before it gets processed or absolute time for
* it to be processed. The latter two allow you to implement timeouts,
* ticks, and other timing-based behavior.
*
* <p>When a
* process is created for your application, its main thread is dedicated to
* running a message queue that takes care of managing the top-level
* application objects (activities, broadcast receivers, etc) and any windows
* they create. You can create your own threads, and communicate back with
* the main application thread through a Handler. This is done by calling
* the same <em>post</em> or <em>sendMessage</em> methods as before, but from
* your new thread. The given Runnable or Message will then be scheduled
* in the Handler's message queue and processed when appropriate.
*/
public class Handler {
}
参考资料
- Android异步音讯处理机制完全解析,带你从源码的视点完全了解
- Android O Handler/HandlerThread/AsyncTask/IntentService
- Handler.postDelayed的原理
- IdleHandler 的原理剖析和妙用
- 什么是Handler的同步屏障机制?
- 【面试题】handler内存泄露的底子原因是?
- 在Android中为啥主张你用Message.obtain()办法获取Message目标,而不是运用new关键字?
- HandlerThread的运用场景和用法
- 【视频:Android开发】handler源码解析,从原理到面试
- Android全面解析之由浅及深Handler音讯机制