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

}



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。