android开发步步为营之60:IntentService与Service的区别

这个面试的时候,相信是面试官最爱的问题之一。简单的来说,IntentService继承至Service,Service和Acitivity一样是依附于应用主进程的,它本身不是一个进程或者一个线程。一些耗时的操作可能会引起ANR的bug,(本文测试的时候,Service执行20秒没有报ANR),而IntentService,看它的源代码,onCreate()其实是创建了一个新的线程。

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app;

import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;

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

    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(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        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();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    protected abstract void onHandleIntent(Intent intent);
}

Looper对象会每次从MessageQueue中获取Intent对象,然后Handler处理消息,调用void onHandleIntent(Intent intent),在这里可以执行一些耗时的比如下载文件等操作。每次调用IntentService都会生成新的HandlerThread,所以不会阻塞UI主线程。如果需要在一个Service里执行耗时操作,那么IntentService是一个很好的选择,不用在Service里面new
Thread()或者New AsyncTask()了那么麻烦了。下面再看看我们本实验的demo,对比Service和IntentService对Acitivity的影响。

       第一步:创建Service和IntentService

package com.figo.study.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class TestService extends Service {

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		try {
			Thread.sleep(20000);
			System.out.print("service执行完成");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return super.onStartCommand(intent, flags, startId);
	}

}
/**
 *
 */
package com.figo.study.service;

import android.app.IntentService;
import android.content.Intent;

/**
 * @author Administrator
 *
 */
public class TestIntentService extends IntentService {

//	public TestIntentService(String name) {
//		// TODO Auto-generated constructor stub
//		super(name);
//	}
	public TestIntentService() {
		super("TestIntentService");
	}

	/* (non-Javadoc)
	 * @see android.app.IntentService#onHandleIntent(android.content.Intent)
	 */
	@Override
	protected void onHandleIntent(Intent intent) {
		// TODO Auto-generated method stub
		try {
			Thread.sleep(20000);
			System.out.print("intentService执行完成");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

        第二步:AndroidManifest.xml注册Service和Activity

        <service
            android:name="com.figo.study.service.TestService"
            android:exported="false" >
            <intent-filter>
                <action android:name="TestService" />
            </intent-filter>
        </service>

        <service
            android:name="com.figo.study.service.TestIntentService"
            android:exported="false" >
            <intent-filter>
                <action android:name="TestIntentService" />
            </intent-filter>
        </service>
        <activity
            android:name="com.figo.study.IntentServiceActivity"
            android:theme="@android:style/Theme.NoTitleBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

第三步:创建测试Activity

/**
 *
 */
package com.figo.study;

import com.figo.study.service.TestIntentService;
import com.figo.study.service.TestService;

import android.app.Activity;
import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;

/**
 * @author figo
 *
 */
public class IntentServiceActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		try {

			setContentView(R.layout.activity_intentservice);
			// 启动一个20秒超时的Service,因为是依附在主线程,可以看到必须等service执行完成之后,页面才会展示出来
			// Intent service=new Intent("TestService");
//			Intent service = new Intent(IntentServiceActivity.this,
//					TestService.class);
//			startService(service);
			// 启动一个20秒超时的IntentService,因为是新建线程,所以页面立刻就展示出来了
//			 Intent intentService=new Intent("TestIntentService");
			 Intent intentService=new
			 Intent(IntentServiceActivity.this,TestIntentService.class);
			 startService(intentService);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
时间: 2024-08-10 23:16:12

android开发步步为营之60:IntentService与Service的区别的相关文章

Android开发之怎样监听让Service不被杀死

一.Service简单介绍 Service是在一段不定的时间执行在后台,不和用户交互应用组件. 每一个Service必须在manifest中 通过<service>来声明. 能够通过contect.startservice和contect.bindserverice来启动.和其它的应用组件一样,执行在进程的主线程中.这就是说假设service须要非常多耗时或者堵塞的操作,须要在其子线程中实现(或者用系统提供的IntentService,它继承了Service,它处理数据是用自身新开的线程).

android开发步步为营之70:android接入Google Analytics总结

求人不如求己,今天项目里要接入Google Analytics,这个是做应用统计分析用的,可以查看当前手机活跃用户,事件点击等等数据,先看看效果: 之前eclipse里面接入已经成功,昨天项目组决定项目转成使用android studio来开发,看google官方文档,官方文档https://developers.google.com/analytics/devguides/collection/android/v4/,然后官方文档里面的配置文件是用google-services.json的,这

android开发教程之开机启动服务service示例

个例子实现的功能是:1,安装程序后看的一个Activity程序界面,里面有个按钮,点击按钮就会启动一个Service服务,此时在设置程序管理里面会看的有个Activity和一个Service服务运行2,如果手机关机重启,会触发你的程序里面的Service服务,当然,手机启动后是看不到你的程序界面.好比手机里面自带的闹钟功能,手机重启看不到闹钟设置界面只是启动服务,时间到了,闹钟就好响铃提醒. 程序代码是: 首先要有一个用于开机启动的Activity,给你们的按钮设置OnClickListener

android开发步步为营之20:网络设置

网络设置这块在手机应用里面是非常重要的一块,因为一般应用都需要和外部网络做交互的.本篇文章就展示了一个比较经典应用场景.比如我最近在开发的转账应用.这个是需要和网络交互的.当用户打开应用之后,应用首先会判断用户是否已经打开wifi或者gprs网络.没有则跳转到系统的无线和网络设置界面,当用户设置好了之后,我这里做了一个更人性化的处理,创建了一个广播接收器,因为我们知道,手机在打开网络或者收到短信的时候,都会对外发布一条广播.一旦网络连接上了之后,我的这个广播接收器,就会收到信息,然后判断当前的转

Android开发学习之路-回调实现Service向activity传递数据

开启服务的时候,如果我们是通过bindService来绑定服务并且要向服务传递数据,可以直接在Intent中设置bundle来达到效果,但是如果是我们需要从服务中返回一些数据到Activity中的时候,实现起来就有各种各样的方法,比如说使用回调,使用广播等等,今天说的是使用回调的方法. 新建一个工程,并编写一个服务: 1 public class MyService extends Service { 2 private boolean connecting = false; 3 private

android开发步步为营之64:PopupWindow实现自定义弹出菜单

打开PopupWindow的源码,你会发现它其实也是通过WindowManager来添加view的. private void invokePopup(WindowManager.LayoutParams p) { if (mContext != null) { p.packageName = mContext.getPackageName(); } mPopupView.setFitsSystemWindows(mLayoutInsetDecor); setLayoutDirectionFro

【Android开发坑系列】如何让Service尽可能存活

流行的思路如下: 1.让Service杀不死.Service的onStartCommand返回START_STICKY,同时onDestroy里面调用startService启动自身. 2.让Service从后台变成前置.在Android 2.0以前有效,借助setForeground(true). 3.让某个进程不被系统的low memory killer杀死(如数据缓存进程,或状态监控进程,或远程服务进程).add android:persistent="true" into th

android开发步步为营之58:给图片绘制圆形气泡背景效果

最近在开发项目的时候,有一个需求,需要给应用图标绘制圆形气泡背景,有了彩色气泡这样显得漂亮一点,气泡的颜色是应用图标的颜色均值,先看看效果,然后,我再给出demo. demo应用图标是这样的: 添加气泡背景后是这样的: 仔细看圆形背景颜色是图标颜色的均值. 好的,下面我们来完成这个demo. 第一步.编写页面activity_drawcycle.xml <?xml version="1.0" encoding="utf-8"?> <LinearLa

android开发步步为营之68:Facebook原生广告接入总结

开发应用的目的是干嘛?一方面当然是提供优质服务给用户,还有一方面最重要的还是须要有盈利.不然谁还有动力花钱花时间去开发app? 我们的应用主攻海外市场,所以主要还是接入国外的广告提供商.本文就今天刚完毕接入facebook原生广告功能,介绍一下怎样接入fb的原生广告.供大家參考.         第一步:申请接入账号(须要FQ) https://developers.facebook.com/docs/audience-network/getting-started#company_info h