`
iaiai
  • 浏览: 2204740 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

IntentService源码详解

 
阅读更多
IntentService可以做什么:
如果你有一个任务,分成n个子任务,需要它们按照顺序完成。如果需要放到一个服务中完成,那么IntentService就会使最好的选择。

IntentService是什么:
IntentService是一个Service(看起来像废话,但是我第一眼看到这个名字,首先注意的是Intent啊。),所以如果自定义一个IntentService的话,一定要在AndroidManifest.xml里面声明。
从上面的“可以做什么”我们大概可以猜测一下IntentService要有什么特性。
首先要明确的是,如果在Activity中启动一个Service,那么这个Service是在主线程中的。所以在IntentService中需要一个工作线程来完成Intent请求。从IntentService的定义可以印证该猜测:
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.

IntentService用来按要求处理异步请求(以Intent的方式发送的)。客户端通过调用startService(Intent)发送请求,服务会按照要求启动,用自己的工作线程(区别于UI主线程)处理每个Intent(请求),当完成所有的请求之后,自动关闭。

IntentService源码解析:
干货来了!IntentService代码包含了一个工作线程Thread、工作线程的Looper、工作线程的Handler。工作线程用来干活的,Looper用来让线程运转起来的,Handler负责向线程传送工作内容的。IntentService的源码简洁透彻的体现了这一个机制。光是看看这个机制就值了。源码如下:
路径:alps\frameworks\base\core\java\android\app\IntentService.java
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) {
//自定义的IntentService子类主要就是实现onHandleIntent这个函数了。注意执行完这个之后就
        //stopSelf了,传入的参数是startId。  
        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();
//好好看看下面这个代码,启动了一个工作线程,获取线程的Looper,然后用这个Looper初始化Handler句柄
//这样以后可以直接用mHandler.sendMessage的方式将任务直接放到工作线程了。 
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");  
    thread.start();  
  
    mServiceLooper = thread.getLooper();  
    mServiceHandler = new ServiceHandler(mServiceLooper);  
}  
  
@Override  
public void onStart(Intent intent, int startId) {
//从消息队列中获取一个消息,一般都是用这种方式初始化一个消息,而不是用new message()形式
    //效率更高,代码更健壮  
    Message msg = mServiceHandler.obtainMessage();  
    msg.arg1 = startId;//  
    msg.obj = intent;//这个就是startService的时候传入的Intent了,  
    mServiceHandler.sendMessage(msg);//将包含请求内容Intent的message传入到工作线程中  
}  
  
/** 
 * 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,和它传入的值。  
        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)}. 
     */  
    protected abstract void onHandleIntent(Intent intent);  
}

从线程分析:
如果是自定义IntentService的话,可以在函数中打印Thread.currentThread().getName()将当前所在线程打印出来。就会发现,只有onHandleIntent的执行是在另外一个新线程中,其他函数(onCreate/onStart/onStartCommand等)的执行都是在main线程(主线程的名称)中。

示例代码:
实际的代码参考如下:
package com.example.fmdemo;  
  
import android.app.IntentService;  
import android.content.Intent;  
import android.os.IBinder;  
import android.util.Log;  
  
public class IntentServiceDemo extends IntentService {  
  
    private static final String TAG = "IntentServiceDemo";  
  
    public IntentServiceDemo() {  
        super("IntentServiceDemo");  
    }  
  
    public IntentServiceDemo(String name) {  
        super(name);  
        // TODO Auto-generated constructor stub  
    }  
  
    @Override  
    protected void onHandleIntent(Intent arg0) {  
        // TODO Auto-generated method stub  
        String action = arg0.getExtras().getString("param");  
        if ("oper1".equals(action)) {  
            Log.i(TAG, "onHandleIntent oper1 threadname = "  
                    + Thread.currentThread().getName());  
        } else if ("oper2".equals(action)) {  
            Log.i(TAG, "onHandleIntent oper2 threadname = "  
                    + Thread.currentThread().getName());  
        }  
  
        try {  
            Thread.sleep(2000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
    }  
  
    @Override  
    public IBinder onBind(Intent intent) {  
        // TODO Auto-generated method stub  
        Log.i(TAG, "onBind threadname = " + Thread.currentThread().getName());  
        return super.onBind(intent);  
    }  
  
    @Override  
    public void onCreate() {  
        // TODO Auto-generated method stub  
        Log.i(TAG, "onCreate threadname = " + Thread.currentThread().getName());  
        super.onCreate();  
    }  
  
    @Override  
    public void onDestroy() {  
        // TODO Auto-generated method stub  
        Log.i(TAG, "onDestroy threadname = " + Thread.currentThread().getName());  
        super.onDestroy();  
    }  
  
    @Override  
    public void onStart(Intent intent, int startId) {  
        // TODO Auto-generated method stub  
        Log.i(TAG, "onStart threadname = " + Thread.currentThread().getName());  
        super.onStart(intent, startId);  
    }  
  
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        // TODO Auto-generated method stub  
        Log.i(TAG, "onStartCommand threadname = "  
                + Thread.currentThread().getName());  
        return super.onStartCommand(intent, flags, startId);  
    }  
  
    @Override  
    public void setIntentRedelivery(boolean enabled) {  
        // TODO Auto-generated method stub  
        Log.i(TAG, "setIntentRedelivery threadname = "  
                + Thread.currentThread().getName());  
        super.setIntentRedelivery(enabled);  
    }  
  
}

在自定义的Activity的onCreate中添加如下代码:
Intent startServiceIntent = new Intent("com.example.fmdemo.intentservice");  
Bundle bundle = new Bundle();  
bundle.putString("param", "oper1");  
startServiceIntent.putExtras(bundle);  
startService(startServiceIntent);  
  
  
Intent startServiceIntent2 = new Intent("com.example.fmdemo.intentservice");  
Bundle bundle2 = new Bundle();  
bundle2.putString("param", "oper2");  
startServiceIntent2.putExtras(bundle2);  
startService(startServiceIntent2);  

运行结果如下:
07-01 06:58:23.557: I/IntentServiceDemo(3732): onCreate threadname = main  
07-01 06:58:23.571: I/IntentServiceDemo(3732): onStartCommand threadname = main  
07-01 06:58:23.571: I/IntentServiceDemo(3732): onStart threadname = main  
07-01 06:58:23.576: I/IntentServiceDemo(3732): onHandleIntent oper1 threadname = IntentService[IntentServiceDemo]  
07-01 06:58:23.577: I/IntentServiceDemo(3732): onStartCommand threadname = main  
07-01 06:58:23.577: I/IntentServiceDemo(3732): onStart threadname = main  
07-01 06:58:25.577: I/IntentServiceDemo(3732): onHandleIntent oper2 threadname = IntentService[IntentServiceDemo]  
07-01 06:58:27.579: I/IntentServiceDemo(3732): onDestroy threadname = main

可以看到onHandleIntent是在不同main主线程的工作线程中运行的。
IntentService使用比较简单,但是实现机制比较有趣。感兴趣的同学可以自己把代码敲进去看看。
分享到:
评论

相关推荐

    android 中的服务Service intentService例子

    **IntentService详解** 1. **单线程模型**:IntentService内部使用了一个工作队列和一个工作线程,保证同一时间只有一个Intent被处理,避免了多线程并发的问题。 2. **自动停止**:IntentService在`onHandleIntent()...

    文件管理器FileManager - 安卓Android程序实例源代码.zip

    对于耗时的操作(如大文件复制或删除),源代码可能会使用`AsyncTask`或者`IntentService`进行后台处理,并通过`Notification`向用户反馈进度。 8. **安全与权限处理** 在Android 6.0(Marshmallow)及以上版本,...

    Android 应用开发详解的源码

    这份"Android应用开发详解的源码"提供了丰富的实例和项目代码,为初学者提供了一个宝贵的资源库,帮助他们深入掌握Android开发技能。以下是这个压缩包中可能包含的一些关键知识点: 1. **Activity生命周期**:...

    《Android应用开发详解》源码(全章节)

    这些只是Android应用开发的部分知识点,通过《Android应用开发详解》的源码学习,你可以深入理解每个概念的实际应用,同时还能看到作者如何解决实际问题,提升自己的编程技巧。在实践中不断探索和学习,才能真正成为...

    Android核心技术与实例详解 随书源码

    《Android核心技术与实例详解》随书源码涵盖了多个章节的内容,包括第4章至第18章的部分章节。这些源代码实例旨在帮助读者深入理解Android开发中的关键技术和实践应用。以下是对各章节涉及知识点的详细解释: 第4章...

    android4.0网络编程详解——源码

    Android提供了AsyncTask、IntentService、Handler/Looper机制和最近的Retrofit、Volley库来实现异步网络请求。理解这些工具的工作原理和使用场景是至关重要的。 **第6章:缓存策略** 为了提高用户体验和减少服务器...

    android核心技术与实例详解 完整源码

    《Android核心技术与实例详解》是一本深入探讨Android开发的书籍,其提供的完整源码是学习和实践Android开发的重要资源。本书涵盖了Android系统的核心组件、框架以及常见应用开发的实例,旨在帮助开发者掌握Android...

    Android应用开发详解教材源码(下册)--实例源码

    在本资源中,"Android应用开发详解教材源码(下册)--实例源码" 提供了8个单元共计30多个实例的源代码,旨在帮助开发者深入理解Android应用程序的开发过程。这些实例覆盖了Android开发中的核心概念、组件以及最佳...

    安卓应用开发源码

    【安卓应用开发源码详解】 在安卓应用开发领域,源码是学习和理解应用程序工作原理的关键。这份"安卓应用开发源码"包含了开发者在实际项目中的实践经验,是深入学习安卓编程的重要资源。通过分析和研究这些源码,你...

    android核心技术与实例详解项目源码

    《Android核心技术与实例详解》是一本深度探讨Android开发的书籍,其项目源码"KDWB_Android"提供了实际操作的示例,对于Android开发者来说,是深入理解Android系统和提升编程技能的重要资源。这个源码主要围绕...

    《android核心技术与实例详解》源码(完整版)

    《Android核心技术与实例详解》是Android开发者们常常参考的一本技术书籍,其源码的完整版为学习者提供了深入理解Android开发的宝贵资源。这本书涵盖了Android应用开发的多个重要方面,包括但不限于UI设计、数据存储...

    android 音乐播放器源码下载

    【Android音乐播放器源码详解】 在Android平台上开发一款音乐播放器是一项常见的任务,而能够获得一份详尽注释的源码无疑是学习和提升的好材料。这个“Android音乐播放器源码”提供了一个完整的实现,从用户界面...

    Android应用开发详解_源码.rar

    此压缩包"Android应用开发详解_源码.rar"可能包含了一系列的示例代码和讲解,旨在帮助初学者或有经验的开发者深入理解Android应用的工作原理。 1. **Android SDK**:Android软件开发工具包(SDK)是开发Android应用...

    Android 动漫阅读器源码.rar

    《Android动漫阅读器源码详解》 Android动漫阅读器源码是专为移动设备设计的一款应用程序,用于在Android平台上浏览和阅读漫画。这份源码提供了一个深入理解Android应用开发,特别是针对多媒体内容展示的绝佳实例。...

    《Android移动开发案例详解》配套CD源码

    源码可能包含使用AsyncTask、IntentService、Loader或现代的协程库(如Kotlin的Coroutines)进行后台操作的实例。此外,可能有关于内存管理、耗电优化和UI流畅性的代码片段。 七、权限管理 随着Android系统的更新,...

    android应用源码(精)饭否客户端最新源码.zip源码资源下载

    《Android应用源码详解——基于饭否客户端》 在Android开发领域,研究开源项目源码是提升技术能力的重要途径之一。本次我们关注的是"饭否客户端"的最新源码资源,这是一份针对Android平台的社交应用源码,旨在帮助...

    android博客阅读器源码

    【Android博客阅读器源码详解】 Android博客阅读器是一款基于Android平台的应用程序,它允许用户浏览和阅读来自不同博客站点的最新文章。源码的分析将深入探讨Android开发中的核心概念和技术,包括网络请求、数据...

    Android 电影购票源码.rar

    《Android 电影购票源码详解》 Android 电影购票源码是一个典型的移动应用开发实例,主要涉及Android平台上的用户界面设计、网络通信、数据处理等多个关键知识点。此源码不仅适用于学习Android应用开发,同时也为...

    Android核心技术与实例详解源码

    本资料"Android核心技术与实例详解源码"提供了丰富的代码示例,旨在帮助开发者深入理解Android系统的运作机制,并能将其运用到实际项目中去。以下是根据标题和描述,以及文件名称列表中的"第17章、第18章"所涉及的...

Global site tag (gtag.js) - Google Analytics