淺析Android 消息機(jī)制

消息機(jī)制存在的意義

  • 為什么不能在非UI線程中操作UI控件?
    因?yàn)锳ndroid的UI控件不是線程安全的,如果在多線程中并發(fā)訪問(wèn)可能會(huì)導(dǎo)致UI控件處于不可預(yù)期的狀態(tài),
  • 為什么不對(duì)UI控件加上鎖機(jī)制?
    首先加上鎖會(huì)讓UI訪問(wèn)的邏輯變得復(fù)雜;其次鎖機(jī)制會(huì)降低UI訪問(wèn)的效率,因?yàn)殒i機(jī)制會(huì)阻塞某些線程的執(zhí)行
  • Android是在哪兒校驗(yàn)UI操作是否是在UI線程?
//ViewRootImpl.java
public ViewRootImpl(Context context, Display display) {
    ... ...
    mThread = Thread.currentThread();
    ... ... 
}

//該方法會(huì)多個(gè)方法的開(kāi)頭被調(diào)用,例如requestLayout()、invalidateChildInParent()等等... ...
void checkThread() {
    if (mThread != Thread.currentThread()) {
        throw new CalledFromWrongThreadException("Only the original thread that created a view hierarchy can touch its views.");
    }
}

消息機(jī)制原理

Android系統(tǒng)主要通過(guò)Message、MessageQueue、Looper、Handler三個(gè)類來(lái)實(shí)現(xiàn)消息處理,其中Message代表消息,MessageQueue是用來(lái)描述消息隊(duì)列,Looper是用來(lái)創(chuàng)建消息隊(duì)列以及進(jìn)入消息循環(huán),Handler 是用來(lái)發(fā)送消息和處理消息。(以下源碼均來(lái)自API 26 Android 8.0,源碼在線查看:http://androidxref.com),先看下整個(gè)事件的整體脈絡(luò),建議根據(jù)圖然后去找對(duì)應(yīng)的函數(shù)調(diào)用。大圖點(diǎn)擊

Handler.jpg

Handler

  • Handler的成員變量
//可能造成內(nèi)存泄露
private static final boolean FIND_POTENTIAL_LEAKS = false;

//是否為異步,默認(rèn)為false
final boolean mAsynchronous;
final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;
  • Handler的創(chuàng)建和獲取
public Handler() { this(null, false); }
public Handler(Callback callback, boolean async) {
    //檢測(cè)內(nèi)存是否存在內(nèi)存泄露的可能
    ... ...
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        //必須先執(zhí)行Looper.prepare()的原因
        throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}
  • 消息發(fā)送
//最基本的消息發(fā)送
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); }
public final boolean sendMessage(Message msg){ return sendMessageDelayed(msg, 0); }
public final boolean sendEmptyMessage(int what){ return sendEmptyMessageDelayed(what, 0); }

//延時(shí)發(fā)送消息
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageDelayed(msg, delayMillis);
}

public final boolean sendMessageDelayed(Message msg, long delayMillis){
    if (delayMillis < 0) {
        delayMillis = 0;
    }

    //SystemClock.uptimeMisllis()是系統(tǒng)啟動(dòng)至今的時(shí)間
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

//在未來(lái)某一確定的時(shí)間點(diǎn)發(fā)送消息(發(fā)送消息最終的調(diào)用在這)
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
}

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    //Message中保存的Handler 對(duì)象
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}
  • 消息處理
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        // 該Callback實(shí)在初始化的時(shí)候傳進(jìn)來(lái)
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

//Handler 的內(nèi)部接口
public interface Callback {
    public boolean handleMessage(Message msg);
}

Looper

  • Looper的重要成員
//存儲(chǔ)不同線程的Looper
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

//主線程的Looper
private static Looper sMainLooper;
final MessageQueue mQueue;
final Thread mThread;
  • Looper的創(chuàng)建和獲取
public static void prepare() {
    prepare(true);
}

private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        //Looper.prepare()只能執(zhí)行一次的原因
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

//準(zhǔn)備主線程的Looper
public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

//Looper構(gòu)造器
private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

//拿到當(dāng)前線程的Looper對(duì)象
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

//拿到主線程的Looper對(duì)象
public static Looper getMainLooper() {
    synchronized (Looper.class) {
        return sMainLooper;
    }
}
  • UI線程中Looper的創(chuàng)建
//ActivityThread.java
public static void main(String[] args) {
    ... ...
    Looper.prepareMainLooper();
    ... ...
    Looper.loop();
    ... ...
}
  • 消息循環(huán)
public static void loop() {
    final Looper me = myLooper();
    final MessageQueue queue = me.mQueue;
    for (;;) {
        Message msg = queue.next();
        if (msg == null) {
            return;
        }
        ... ...
        msg.target.dispatchMessage(msg);
    }
}

MessageQueue

  • MessageQueue的重要成員
//該MessageQueue是否可退出,通過(guò)Looper.prepare()創(chuàng)建的都是可退出的,UI線程的MessageQueue是不可以退出的
private final boolean mQuitAllowed;
//當(dāng)前消息隊(duì)列的頭部    
Message mMessages;
//C++層NativeMessageQueue的地址
private long mPtr; 
//是否處于阻塞狀態(tài) 
private boolean mBlocked;
  • MessageQueue的創(chuàng)建
MessageQueue(boolean quitAllowed) {
    mQuitAllowed = quitAllowed;
    //JNI調(diào)用初始化 C++ 層的 NativeMessageQueue.cpp
    mPtr = nativeInit();
}
  • 消息入隊(duì)
boolean enqueueMessage(Message msg, long when) {
    ... ...
    synchronized (this) {
        ... ...
        msg.when = when;
        Message p = mMessages; 
        boolean needWake;

        //頭部等于空,或者入隊(duì)消息的時(shí)間小于當(dāng)前時(shí)間就插到隊(duì)首
        if (p == null || when == 0 || when < p.when) {
            msg.next = p;
            mMessages = msg;
            needWake = mBlocked;
        } else {
            //尋找隊(duì)尾或者在自己發(fā)送時(shí)間之后的位置,然后插入隊(duì)列中
            needWake = mBlocked && p.target == null && msg.isAsynchronous();
            Message prev;
            for (;;) {
                prev = p;
                p = p.next;
                if (p == null || when < p.when) {
                    break;
                }
                if (needWake && p.isAsynchronous()) {
                    needWake = false;
                }
            }
            msg.next = p; 
            prev.next = msg;
        }
        if (needWake) {
            //JNI調(diào)用,喚醒NativeMessageQueue
            nativeWake(mPtr);
        }
    }
    return true;
}
  • 消息出隊(duì)
Message next() {    
    //執(zhí)行下一條消息時(shí)還需要等待的時(shí)間,當(dāng)為-1時(shí)代表消息隊(duì)列中沒(méi)有消息,則無(wú)限等待
    int nextPollTimeoutMillis = 0;
    for (;;) {
        ... ...
        //JNI調(diào)用,阻塞操作,當(dāng)?shù)却齨extPollTimeoutMillis時(shí)長(zhǎng),或者消息隊(duì)列被喚醒,都會(huì)返回
        nativePollOnce(ptr, nextPollTimeoutMillis);
        synchronized (this) {
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
            ... ...
            if (msg != null) {
                if (now < msg.when) {
                    //當(dāng)異步消息觸發(fā)時(shí)間大于當(dāng)前時(shí)間,則設(shè)置下一次輪詢的超時(shí)時(shí)長(zhǎng)
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    // 獲取一條消息,并返回
                    mBlocked = false;
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                     //成功地獲取MessageQueue中的下一條即將要執(zhí)行的消息
                    return msg;
                }
            } else {
                //沒(méi)有消息
                nextPollTimeoutMillis = -1;
            }
            //消息正在退出,返回null(調(diào)用了quit()方法)
            if (mQuitting) {
                dispose();
                return null;
            }
            ... ...
        }
        ... ...
    }
}

NativeMessageQueu

//Java層中MessageQueue的nativaInit()方法
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
    NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
    ... ...
    //將NativeMessageQueue對(duì)象的指針強(qiáng)轉(zhuǎn)為Java中的long類型并返回
    return reinterpret_cast<jlong>(nativeMessageQueue);
}
  • NativeMessageQueue的構(gòu)造器
//和Java層的MessageQueue的構(gòu)造器很類似
NativeMessageQueue::NativeMessageQueue() : mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
    //獲取當(dāng)前線程的Looper,類似Java層的myLooper()
    mLooper = Looper::getForThread();
    if (mLooper == NULL) {
        mLooper = new Looper(false);
        Looper::setForThread(mLooper);
    }
}

Looper.cpp

  • 構(gòu)造器
Looper::Looper(bool allowNonCallbacks)  {
    //構(gòu)造一個(gè)喚醒事件的文件描述符,能在用戶態(tài)用做事件wait/notify機(jī)制,通過(guò)內(nèi)核取喚醒用戶態(tài)的事件。
    //這個(gè)對(duì)象保存了一個(gè)內(nèi)核維護(hù)的uint64_t類型的整型counter。這個(gè)counter初始值被參數(shù)一指定,一般初值設(shè)置為0。
    //read:如果計(jì)數(shù)值counter的值不為0,讀取成功,獲得到該值。如果counter的值為0,非阻塞模式,會(huì)直接返回失敗,并把errno的值指紋EINVAL。
    //如果為阻塞模式,一直會(huì)阻塞到counter為非0位置。
    //write:會(huì)增加8字節(jié)的整數(shù)在計(jì)數(shù)器counter上,如果counter的值達(dá)到0xfffffffffffffffe時(shí),就會(huì)阻塞。直到counter的值被read。阻塞和非阻塞情況同上面read一樣。
    mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    ... ...
}
  • 喚醒鎖
void Looper::wake() {
    uint64_t inc = 1;
    //向喚醒事件的文件中寫(xiě)入數(shù)據(jù)
    write(mWakeEventFd, &inc, sizeof(uint64_t));
}
  • 輪詢
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    int result = 0;
    for(;;){
        ... ... 
        if (result != 0) {
            ... ...
            return result;
        }
        result = pollInner(timeoutMillis);
    }
}
int Looper::pollInner(int timeoutMillis) {
    ... ...
    //等待被喚醒,喚醒時(shí)間為timeoutMillis,如果timeoutMillis<0,則等待I/O事件喚醒
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    ... ...
    for (int i = 0; i < eventCount; i++) {
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        if (fd == mWakeEventFd) {
            if (epollEvents & EPOLLIN) {
                awoken(); //已經(jīng)喚醒了,則讀取并清空管道數(shù)據(jù)
            }
        } else {
            ... ...
        }
        ... ...
    }
    ... ...     
    return result;
}
void Looper::awoken() {
    uint64_t counter;
    //不斷讀取管道數(shù)據(jù),目的就是為了清空管道內(nèi)容
    TEMP_FAILURE_RETRY(read(mWakeEventFd, &counter, sizeof(uint64_t)));
}

疑點(diǎn)

Looper.loop()已經(jīng)進(jìn)入死循環(huán),那么主線程的其他操作是如何執(zhí)行的?

  • 首先從線程的角度分析:一個(gè)線程是會(huì)在什么時(shí)間結(jié)束?很明顯是該線程中的代碼執(zhí)行完成后就會(huì)結(jié)束,然后該線程就會(huì)被JVM回收。那么如何保證一個(gè)線程永遠(yuǎn)處于運(yùn)行狀態(tài)?貌似只有死循環(huán)。所以這么設(shè)計(jì)肯定是合理的,不然主線程早已被回收了,之所以一直存在就是因?yàn)長(zhǎng)ooper.loop()一直在執(zhí)行。
  • 這時(shí)候第二個(gè)問(wèn)題就出現(xiàn)了,如果Looper.loop()一直在阻塞等待,那么UI的繪制是如何執(zhí)行?那么只能從MainLooper的源頭查起,沒(méi)錯(cuò)就是ActivityThread:
final ApplicationThread mAppThread = new ApplicationThread();
final H mH = new H();
public static void main(String[] args) {
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    //這時(shí)候就是進(jìn)入死循環(huán),一旦退出循環(huán)直接拋出異常
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}
//ActivityThread的內(nèi)部類,在這個(gè)類中有許多發(fā)送消息的方法,并且從方法中的參數(shù)可以看出都是與UI線程相關(guān)的操作,并且我們知道Binder的服務(wù)端都是運(yùn)行在Binder線程池中
private class ApplicationThread extends IApplicationThread.Stub {
    @Override
    public final void scheduleLaunchActivity(... ...) {
        ... ...
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }    

    public final void schedulePauseActivity(... ...) {
        ... ...
        sendMessage(finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, ... ...);               
    }
    ... ...
}
//ActivityThread的內(nèi)部類,該類繼承自Handler,并且處理的消息都是與UI線程相關(guān)
private class H extends Handler {
    switch (code) {
        case LAUNCH_ACTIVITY: 
            ... ...
            handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            break;
        case PAUSE_ACTIVITY: 
            handlePauseActivity(... ...);
            break;
        ... ...
    }
}

所以根據(jù)以上代碼,可以大致分析出,UI線程本質(zhì)的的所有操作都是有MainHanlder來(lái)進(jìn)行處理,而發(fā)送這些消息的操作就分別在不同的子線程中,例如與生命周期相關(guān)的都是在ApplicationThread的線程中,下面從網(wǎng)上盜了張圖:Android中為什么主線程不會(huì)因?yàn)長(zhǎng)ooper.loop里的死循環(huán)卡死?

image.png

所以說(shuō)主線程不能獨(dú)活,必須依賴于其他線程來(lái)給主線程發(fā)送消息,而我們自己在主線程里面發(fā)送消息無(wú)疑是來(lái)自于另一個(gè)線程先發(fā)的消息,例如我們經(jīng)常會(huì)在Activity的生命周期中進(jìn)行發(fā)送消息,而這些生命周期方法的執(zhí)行也是來(lái)自與另一個(gè)線程的消息,就相當(dāng)于我們?cè)?code>handlerMessage方法中再次發(fā)送消息下面的Demo可以說(shuō)明上述結(jié)論是正確的。

public class MainActivity extends AppCompatActivity {
    private Handler handler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d("TestHandler","Start Thread One");
                Looper.prepare();
                handler = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        Log.d("TestHandler",msg.what+" = "+System.currentTimeMillis());
                        if (msg.what == 3){
                            Log.d("TestHandler","send Message!");
                            sendEmptyMessageDelayed(4,1000);
                            sendEmptyMessage(5);
                        }
                    }
                };
                Looper.loop();
                handler.sendEmptyMessageDelayed(1,500);
                handler.sendEmptyMessage(2);
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d("TestHandler","Start Thread Two");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                handler.sendEmptyMessage(3);
            }
        }).start();
    }
}

//輸出
03-21 22:21:31.132 21995-22032/? D/TestHandler: Start Thread One
03-21 22:21:31.133 21995-22033/? D/TestHandler: Start Thread Two
03-21 22:21:31.633 21995-22032/? D/TestHandler: 3 = 1521642091633
03-21 22:21:31.633 21995-22032/? D/TestHandler: send Message!
03-21 22:21:31.633 21995-22032/? D/TestHandler: 5 = 1521642091633
03-21 22:21:32.635 21995-22032/com.whf.test D/TestHandler: 4 = 1521642092635?

內(nèi)存泄露問(wèn)題

  • 為什么會(huì)發(fā)生內(nèi)存泄露?
    • Java 回收機(jī)制是根據(jù)可達(dá)性來(lái)判別,即一個(gè)對(duì)象如果是沒(méi)有被其他對(duì)象引用(即不可達(dá)的),這時(shí)候在GC的過(guò)程就會(huì)把這個(gè)對(duì)象列為可回收的,在下一次的GC的時(shí)候就會(huì)執(zhí)行回收。
    • 一個(gè)非靜態(tài)內(nèi)部類會(huì)持有外部類的引用。
    • Message對(duì)象的taget屬性引用了Handler對(duì)象。
      基于以上三點(diǎn)可知,當(dāng)一個(gè)Activity中有一個(gè)非靜態(tài)的Hanlder類,該Handler類就會(huì)持有該Activity的引用,如果當(dāng)該Activitv退出的時(shí)候,其內(nèi)部的Handler發(fā)送的Message還沒(méi)有被處理完,而這些Message對(duì)象都會(huì)持有該Activity的引用,所以就會(huì)導(dǎo)致Activity無(wú)法被回收,從而造成內(nèi)存泄露。
  • Handler如何避免內(nèi)存泄露?
    • 以靜態(tài)內(nèi)部類或外部類的形式存在,不要在Activity中寫(xiě)非靜態(tài)的Handler類
    • Handler的靜態(tài)內(nèi)部類訪問(wèn)外部類時(shí)采用弱引用
    • 在Activity回收前,清空MessageQueue中存儲(chǔ)的該Handler發(fā)送的Message,通過(guò)調(diào)用Handler的removeCallbackAndMessages()方法,該方法原理如下:
//Handle
public final void removeCallbacksAndMessages(Object token) {
    mQueue.removeCallbacksAndMessages(this, token);
}
//MessageQueue
void removeCallbacksAndMessages(Handler h, Object object) {
    synchronized (this) {
        Message p = mMessages;     
        while (p != null && p.target == h && (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }

        while (p != null) {
            Message n = p.next;
            if (n != null) {
                if (n.target == h && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}

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() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    @NonNull
    public Handler getThreadHandler() {
        if (mHandler == null) {
            mHandler = new Handler(getLooper());
        }
        return mHandler;
    }

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

IntentService

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(int)來(lái)保證你當(dāng)前停止Service的請(qǐng)求是基于上一個(gè)請(qǐng)求的。也就是說(shuō),當(dāng)你調(diào)用stopSelf(int),你把startID傳給了對(duì)應(yīng)的要停止的Service,
            //這個(gè)startID是上一個(gè)請(qǐng)求的StartID!!如果沒(méi)有第二個(gè)請(qǐng)求來(lái),那么這個(gè)Service就會(huì)死掉,但是如果這個(gè)Service已經(jīng)又接受到一個(gè)新的啟動(dòng)請(qǐng)求之后,
            //你才調(diào)用stopSelf(int),那么你傳遞給stopSelf()的ID是上一個(gè)請(qǐng)求的ID,而當(dāng)前Service的startID已經(jīng)更新為新的請(qǐng)求的ID,造成兩個(gè)ID不對(duì)應(yīng),stopSelf()失效,
            //那么Service就不會(huì)停止。這樣就避免了將后面的請(qǐng)求終止
            stopSelf(msg.arg1);
        }
    }

    public IntentService(String name) {
        super();
        mName = name;
    }

    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
        mServiceLooper = thread.getLooper();
        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();
    }

    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容