Android Service

Service 和 Thread 的区别和场景

  • Thread:程序执行的最小单元,它是分配 CPU 的基本单位

简单地说,服务是一种即使用户未与应用交互也可在后台运行的组件,因此,只有在需要服务时才应创建服务。

如果您必须在主线程之外执行操作,但只在用户与您的应用交互时执行此操作,则应创建新线程。

Service 的生命周期

图 1 服务生命周期

Service 和 IntentService 的区别

Service 运行在主线程中,直接使用做耗时任务会卡主线程,从而导致 ANR。Service ANR 的时间为前台 Service 20 秒,后台 Service 200 秒。Service 不会自动停止。
而 IntentService 会开启子线程,重写 onHandleIntent 方法中处理逻辑即可,不会引发 ANR。IntentService 内部有一个工作线程 HanderThread 来处理耗时操作。任务结束后 IntentService 会自动停止。

IntentService 是一个抽象类,继承自 Service,内部存在一个 ServiceHandler(Handler)和 HandlerThread(Thread)。IntentService 是处理异步请求的一个类,在 IntentService 中有一个工作线程(HandlerThread)来处理耗时操作,启动 IntentService 的方式和普通的一样,不过当执行完任务之后,IntentService 会自动停止。另外可以多次启动 IntentService,每一个耗时操作都会以工作队列的形式在 IntentService 的 onHandleIntent 回调中执行,并且每次执行一个工作线程。IntentService 的本质是:封装了一个 HandlerThread 和 Handler 的异步框架。

IntentService 源码

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

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

IntentService 内部通过消息的方式发送给 HandlerThread,然后由 Handler 中的 Looper 来处理消息。

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

boolean wasInterrupted = false;

// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
wasInterrupted = true;
}
}
}

if (wasInterrupted) {
Thread.currentThread().interrupt();
}

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

启动服务和绑定服务顺序

先绑定服务后启动服务

绑定服务会转为启动服务状态

先启动服务后绑定服务

启动服务不会转为绑定服务

总结

启动服务的优先级比绑定服务高
服务在其托管进程的主线程中运行 (UI 线程)

Parcelable 和 Serializable

Serializable 实现简单,内存开销大
Parcelable 性能比 Serializable 好,内存开销小,实现比 Serializable 复杂

内存中传输使用 Parcelable
存储到设备中使用 Serailizable

可靠便捷的VPN服务 100 G 月流量,5台设备可用,一年仅需99元!
请我一杯咖啡吧!
八亩山啊 微信 微信
八亩山啊 支付宝 支付宝
八亩山啊 比特币 比特币
  • 本文作者: 八亩山啊
  • 本文链接: https://mumo.fun/posts/15/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!