Android IntentService

本文深入解析Android中的IntentService组件,探讨其作为Service子类的工作原理,包括如何在子线程中处理耗时任务,以及如何利用HandlerThread实现任务调度。通过示例代码,展示了IntentService的创建、启动和停止过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目地址:项目地址包含之前的内容

  • 类介绍
  • 使用示例
  • 源码浅析
  • 总结

类介绍

public abstract class IntentService extends Service {
	...
	protected abstract void onHandleIntent(@Nullable Intent intent);
	...
}

首先IntentService是一个继承自Service的抽象类,一个抽象方法onHandleIntent,用来处理具体任务。
注释中介绍:它会根据客户端通过startService(Intent intent)发起的请求,开启工作线程,依次处理。会调用onHandleIntent抽象方法,并传入参数。处理具体的任务。

使用示例

前面介绍过Service的使用。IntentService有些大同小异而已。

  1. MyIntentService
public class MyIntentService extends IntentService {
    protected String TAG=getClass().getSimpleName()+"----";
    public MyIntentService() {
        this(null);
    }

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */

    public MyIntentService(String name) {
        super(name);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("life",TAG+"onCreate--threadName: "+Thread.currentThread().getName());
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.i("life",TAG+"onStart--threadName: "+Thread.currentThread().getName());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("life",TAG+"onStartCommand--threadName: "+Thread.currentThread().getName());
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("life",TAG+"onDestroy--threadName: "+Thread.currentThread().getName());
    }


    @Override
    public IBinder onBind(Intent intent) {
        Log.i("life",TAG+"onBind--threadName: "+Thread.currentThread().getName());
        return super.onBind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i("life",TAG+"onUnbind--threadName: "+Thread.currentThread().getName());
        return super.onUnbind(intent);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        try {
        	//休眠2秒钟
            Thread.sleep(1000*2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.i("life",TAG+"onHandleIntent--threadName: "+Thread.currentThread().getName());

    }
}

这里log了生命周期,有助于方法调用的理解。其中onHandleIntent方法中休眠了2秒钟。
2. Activity中

	//创建intent和ServiceConnection 
	private Intent intent;
    private ServiceConnection conn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_intent_service);
        ButterKnife.bind(this);
        intent=new Intent(this, MyIntentService.class);
        conn=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {

            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        };
    }
//点击事件
 @OnClick({R.id.start, R.id.stop, R.id.bindService, R.id.unbindService})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.start:
                startService(intent);
                break;
            case R.id.stop:
                stopService(intent);
                break;
            case R.id.bindService:
                bindService(intent,conn,Context.BIND_AUTO_CREATE);
                break;
            case R.id.unbindService:
                unbindService(conn);
                break;
                default:
        }
    }

连续点击startService之后的log。
IntentService
可以看出,Service只有一个线程,每次任务完成后在进行下次任务,知道所有任务完成,在onDestroy自己。
如果想得到任务的返回结果就需要绑定了。这里就不在累述了。

源码浅析

通过生命周期的顺序来看

  1. 构造方法
 /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public IntentService(String name) {
        super();
        mName = name;
    }

需要传入一个名字,用来给线程命名。
2. onCreate

  @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();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
    

这里直接实例化了一个HandlerThread,并设置了名字。然后提供了一个Handler对象。等下再看ServiceHandler代码。
3. onStartCommand

 @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

    /**
     * You should not override this method for your IntentService. Instead,
     * override {@link #onHandleIntent}, which the system calls when the IntentService
     * receives a start request.
     * @see android.app.Service#onStartCommand
     */
    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

onStartCommand的方法和Service的不同之处是调用了一个onStart方法。而onStart方法发送了一个Message。而且方法也提示了,我们不需要在重写这个方法,而应该重写onHandleIntent方法。因为消息发出后,会自动的调用onHandleIntent。 mRedelivery 稍后再看

  1. ServiceHandler
 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);
        }
    }

收到消息后获得intent调用onHandleIntent方法,之后调用stopSelf。也就是说IntentService的内部实现靠的是HandlerThread。

  1. setIntentRedelivery
public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

如果此参数为true,onStartCommand将返回START_REDELIVER_INTENT ,否则返回START_NOT_STICKY。
START_REDELIVER_INTENT :如果onHandleIntent还没有执行完成,进程就被杀死了,进程将会被重启,并且携带会原来的Intent。如果有多任务的话,自会保留最后一个Intent。
START_NOT_STICKY:进程不会被重启,Intent也一起销毁。

总结

  1. IntentService利用HandlerThread,对我提供一个在子线程中执行的方法onHandleIntent
  2. 耗时任务完成后,会调用stopSelf,来结束自己。
  3. 如果绑定了IntentService,startService之后,destroy自己。
  public final void stopForeground(@StopForegroundFlags int flags) {
        try {
            mActivityManager.setServiceForeground(
                    new ComponentName(this, mClassName), mToken, 0, null, flags);
        } catch (RemoteException ex) {
        }
    }

mActivityManager是IActivityManager的对象,看不到源码。估计和mToken有关,mToken是一个IBinder对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值