半栈工程师Android知识Android开发

安卓intentService源码

2018-04-14  本文已影响0人  勤能不能补拙

IntentService是handlerThread与Service的结合,因为实质是串行的执行,所以该service不适合执行频繁的网络请求类型的操作,但是他是一个用完自动停止的service,并且减轻主线程looper的压力,所以非常 适合做一些非及时性的耗时操作,如后台数据统计等.

用法
创建一个intentService,模拟一个耗时操作,发送一个广播到ui

public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    /**
     * 这是子线程,不需要再开一个线程了
     *
     * @param intent
     */
    @Override
    protected void onHandleIntent(Intent intent) {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //创建Intent
            Intent intent1 = new Intent();
            intent1.setAction("myintentService.reciver");
            intent1.putExtra("string", i + "次刷新");
            //发送广播
            sendBroadcast(intent1);
        }
    }
}

ui开启服务,接受广播

public class MainActivity extends AppCompatActivity {

    private TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = findViewById(R.id.tv);
        MyReciver myReciver = new MyReciver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("myintentService.reciver");
        registerReceiver(myReciver, intentFilter);
        Intent intent = new Intent(this, MyIntentService.class);
        startService(intent);

    }

    private class MyReciver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String string = intent.getStringExtra("string");
            MainActivity.this.text.setText(string);
        }
    }
}

用完之后该service就停止了,当多次启动会多次执行onHandleIntent,因为原理是handler,looper来实现的,所以是串行,启动之后实则是发送一个消息.

源码
intentService的源码很简单,只有一百多行代码

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

先看构造函数,这里穿了一个线程的名字

    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

再看onCreat()方法,在这里呢创建了一个handlerThread线程,并且开始执行,然后获取该线程的looper,然后赋值给handler,handler的执行型线程取决与该looper的线程,

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

再看这个onStart方法,这里启动的时候默认发送了一个消息,将intent复制给msg

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

再看这个handler做了什么,handler接受到消息的时候调用onHandleIntent去执行,然后调用stopSelf去停止服务

   public final void stopSelf(int startId) {
        if (mActivityManager == null) {
            return;
        }
        try {
            mActivityManager.stopServiceToken(
                    new ComponentName(this, mClassName), mToken, startId);
        } catch (RemoteException ex) {
        }
    }

再看stopSelf,该方法通过stopServiceToken停止掉了service,但是service没有被马上杀死,所以就形成了一个串行的执行,这里的startId是AMS为starService创建的一个id号,默认是递增的一个数,所以每次startService的时候都会+1,也可以认为是启动的次数,每次handler执行完消息的时候都会调用一次stopSelf,stopSelf的本身其实是根据startId来关闭服务的,只有startId是最后一起启动时候的startId才会去停掉,这也就解释了为什么多次启动IntentService会多次执行handlerIntent

 @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

mServiceLooper.quit(),该方法是将队列中的所有消息移除,并且停止循环

上一篇 下一篇

猜你喜欢

热点阅读