一言以蔽之总括一下,而IntentService(Service)是把任务放在子线程中施行的

IntentService

前几日学习了Service,此间是笔记,是时候来上学一下Intent瑟维斯(Service)了.

依然,先看下官网介绍:

IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand. Clients send requests
through 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.
This “work queue processor” pattern is commonly used to offload tasks
from an application’s main thread. The IntentService class exists to
simplify this pattern and take care of the mechanics. To use it,
extend IntentService and implement onHandleIntent(Intent).
IntentService will receive the Intents, launch a worker thread, and
stop the service as appropriate.
All requests are handled on a single worker thread — they may take as
long as necessary (and will not block the application’s main loop),
but only one request will be processed at a time.

简单易行总计一下:
service的子类,用于拍卖异步请求,并且在工作线程按顺序处理请求,工作完后自己截止.
利用也很简短,继承Intent瑟维斯,实现onHandleIntent(Intent)形式即可.
特点:

  1. 与Service不同,Intent瑟维斯(Service)(Service)是起线程处理任务的
  2. 自带队列,每个请求都会排队
  3. 职责成功自己会调用stopSelf竣工,无需我们担心

Intent瑟维斯(Service)(Service)使用及源码分析


**转载请申明原博客地址:
**

一研商竟

Intent瑟维斯(Service)(Service)源码不多,截取了部分:

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
            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();
        //getLooper 来获取thread的looper
        mServiceLooper = thread.getLooper();
        //拿looper实例化 handler
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        //封装intent的请求 用handler发送
        mServiceHandler.sendMessage(msg);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
      //退出循环
        mServiceLooper.quit();
    }

    protected abstract void onHandleIntent(Intent intent);
}

分子变量不多,一个looper,一个handler,接下去分析一下:
在onCreate里,实例化一个HandlerThread(继承自Thread,HandlerThread前边再说)并且启动线程,并且采用该HandlerThread线程的looper实例化handler.
onStart里收受的intent,封装成Message用handler发送,并在handleMessage中调用onHandleIntent((Intent)msg.obj);,再stopSelf.
另外在onDestroy里调用了looper.quit();退出looper.

这般intentService(Service)的机制原理也大多看完了,其实不难,但是也能学到不少东西:

  1. HandlerThread类–>官方资料

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.

有利我们创造一个拥有looper的线程,可以用来创造handler.注意: start()必须被调用!

在此以前也不亮堂这些类,本次索性来探望HandlerThread的源码:

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;

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

    /**
     * This method returns the Looper associated with this thread. If this thread not been started
     * or for any reason is isAlive() returns false, this method will return null. If this thread
     * has been started, this method will block until the looper has been initialized.  
     * @return The looper.
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }

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

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

我们都了然在线程里实例化handler要调用Looper.prepare();Looper.loop();,其实就是因为Looper
而HandlerThread有个分子变量mLooper,并且在run里面实例化了它,并且已经为我们封装好了Looper相关的主意~

注意getLooper艺术,当mLooper为null时会一向wait,直到run方法里实例化mLooper并notifyAll,可以学学一下.

用法就拿一下Intent瑟维斯(Service)里的代码吧:

HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
  1. Handler类的handleMessage艺术所在的线程决定于它的Looper所在的线程,那几个以前一向没留意.

本篇博客紧要简介一下两个问题:

  1. 什么是IntentService?
  2. 什么样利用Intent瑟维斯(Service)
  3. IntentSerice()源码分析

总结

重要学习到了:

  1. 可以采纳Handler去维护一个队列,很简短
  2. HandlerThread类
  3. Handler的handleMessage措施所在的线程决定于它的Looper所在的线程

Intent瑟维斯(Service)代码虽少,可是这多少个好.
其它,Android还有好多很好的类需要自己去发现,去上学!~
又学了一招,哈哈!~

另外欢迎关注:
我的Github
我的新浪
自己的微信公众号:

微信公众号

1)什么是IntentService?

咱俩知晓Service(Service)和Activity一样是Android的四大组件之一,瑟维斯(Service)简称为后台服务,具有较高的先行级别。咱们平昔在Activity中直接打开瑟维斯(Service)(Service),是运行在主线程的。假设想要执行耗时任务,我们亟须团结打开线程。而Intent瑟维斯(Service)是把任务放在子线程中施行的。

  • 咱俩先来看一下法定的解析是什么样的?

This “work queue processor” pattern is commonly used to offload tasks
from an application’s main thread. The IntentService class exists to
simplify this pattern and take care of the mechanics. To use it,
extend IntentService and implement onHandleIntent(Intent).
IntentService will receive the Intents, launch a worker thread, and
stop the service as appropriate.
All requests are handled on a single worker thread — they may take as
long as necessary (and will not block the application’s main loop),
but only one request will be processed at a time.
大概来说根本有眨眼之间间几点

  1. 瑟维斯(Service)(Service)是运作在子线程的;
  2. 四个请求会按启动的次第执行,不过一遍只会处理一个职责;
  3. 任务履行完毕之后会活动退出瑟维斯(Service)(Service),不需要我们和好处理

2)下边我们来看一下我们要如何使用Intent瑟维斯?

实则跟普通的瑟维斯(Service)(Service)差不多

  • 1)自定义一个MyIntentService集成Intent瑟维斯(Service),重写构造方法和onHandleIntent方法,在HandleIntent里面实践我们的耗时任务等操作

public class MyIntentService extends IntentService {

    private static final String ACTION_DOWNLOAD = "com.szl.intentservicedemo.action.DOWNLOAD";
    private static final String ACTION_UPLOAD = "com.szl.intentservicedemo.action.UPLOAD ";


    private static final String EXTRA_PARAM1 = "com.szl.intentservicedemo.extra.PARAM1";
    private static final String EXTRA_PARAM2 = "com.szl.intentservicedemo.extra.PARAM2";
     public static final String TAG="tag";

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

   //这里省略了若干个方法


    //处理我们启动的Service
    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            final String action = intent.getAction();
            if (ACTION_DOWNLOAD.equals(action)) {
                final String param1 = intent.getStringExtra(EXTRA_PARAM1);
                final String param2 = intent.getStringExtra(EXTRA_PARAM2);
                handleDOwnload(param1, param2);
            } else if (ACTION_UPLOAD.equals(action)) {
                final String param1 = intent.getStringExtra(EXTRA_PARAM1);
                final String param2 = intent.getStringExtra(EXTRA_PARAM2);
                handleUpload(param1, param2);
            }
        }
    }


}
  • 2)别忘了在清单文件之中注册我们的瑟维斯(Service)

 <service
  android:name=".MyIntentService"
  android:exported="false">
 </service>
  • 3)启动大家的瑟维斯(Service)(Service),这里运用context.start瑟维斯(Service)(intent)启动,当然你也可以用bind瑟维斯(Service)(Service)启动

Intent intent = new Intent(context, MyIntentService.class);
intent.setAction(ACTION_UPLOAD);
intent.putExtra(EXTRA_PARAM1, param1);
intent.putExtra(EXTRA_PARAM2, param2);
context.startService(intent);

测试代码如下

public void onButtonClick(View view) {
    switch (view.getId()) {
        case R.id.btn_download:
            MyIntentService.startActionDownLoad(MainActivity.this, "下载", "发起者主线程");
            break;

        case R.id.btn_upload:
            MyIntentService.startActionUpload(MainActivity.this, "上传", "发起者主线程");
            break;

        default:
            break;
    }
}

运转以上测试程序,依次点击模拟上传和模拟下载,将可在我们的控制台上看看以下的log消息

公海赌船网站 1

支配台出口的Log

公海赌船网站 2


Intent瑟维斯(Service)源码分析

这里先贴出Intent瑟维斯(Service)(Service)的源码

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(msg.arg1);
        }
    }

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

    /**
     * Sets intent redelivery preferences.  Usually called from the constructor
     * with your preferred semantics.
     *
     * <p>If enabled is true,
     * {@link #onStartCommand(Intent, int, int)} will return
     * {@link Service#START_REDELIVER_INTENT}, so if this process dies before
     * {@link #onHandleIntent(Intent)} returns, the process will be restarted
     * and the intent redelivered.  If multiple Intents have been sent, only
     * the most recent one is guaranteed to be redelivered.
     *
     * <p>If enabled is false (the default),
     * {@link #onStartCommand(Intent, int, int)} will return
     * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent
     * dies along with it.
     */
    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

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

    @Override
    public void onStart(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(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

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

    /**
     * Unless you provide binding for your service, you don't need to implement this
     * method, because the default implementation returns null. 
     * @see android.app.Service#onBind
     */
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * 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)}.
     */
    @WorkerThread
    protected abstract void onHandleIntent(Intent intent);
}

源码分析

剖析以前大家先来看一下Service生命周期

公海赌船网站 3

此处我们以start瑟维斯(Service)()为例分析,从大家启动一个Intent瑟维斯(Service),调用的进程大约是这么的,

构造方法 ->onCreate()- >onStartCommand()-
>onStart()->Service(Service) running–>

  • 1)首先我们先来看一下构造方法里面做了怎么工作

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

实则很粗略,只是调用父类的构造方法,并保留我们的那么字段

  • 2)接着我们来看大家的onCreate方法做了什么样?

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

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

概括的话,就是为我们起首化一个线程thread并启动它,并将线程的looper与我们的m瑟维斯(Service)Handler绑定在联合。

  • 3)接着我们来看onStartCommand()方法做了什么样?

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

大家可以寓目在onStartCommand转调了onStart()方法

  • 4)onStart()方法

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

公海赌船网站,在onStart()方法里面其实就是用我们的mService(Service)Handler发送音讯(mServiceHandler.sendMessage(msg);),这样在大家handleMessage()里面讲能够接过大家的音信,在handleMessage()里面有调用onHandleIntent()去处理大家的Intent,这就是怎么我们需要重写onHandleIntent的原因。

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);
    }
}
  • 5)至于下边提到的大家的handleIntent是运作在子线程的,其实也很容易通晓,因为我们知晓handle运行在主线程如故子线程,是在于我们与特别线程的looper绑定在一个的,而Intent瑟维斯在onCreate方法少校大家的mServiceHandler与子线程的looper绑定在联名。核心代码呈现如下

mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
  • 6)为何四个请求会按启动的相继执行,可是两遍只会处理一个职责?
    大家明白多次调用context.startService方法,不会一再调用大家的onCreate()方法,但会调用我们的onStart()方法,而在大家的onStart()方法里面我们调用m瑟维斯Handler.sendMessage(msg);相当于是向信息队列之中插入一条音信,Looper会不断地从中间取出信息,交给相应
    的hanlder处理,直到没有新闻停止。假使对Handler新闻机制不通晓的话,指出先去打听
  • 7)为何任务履行完毕之后会活动退出Service,不需要大家温馨处理?
    以此就很简短了,因为在处理完信息之后,会调用stopSelf去截至相应的劳动。

public void handleMessage(Message msg) {
    onHandleIntent((Intent)msg.obj);
    stopSelf(msg.arg1);
}

到此Intent瑟维斯(Service)(Service)源码分析地方

关于HandlerThread的解析,可以查看自己的 这一篇博客
HandlerThread源码分析

**转载请申明原博客地址:
**

**事例源码下载地址:
**

相关文章