您的位置:首页 > 移动开发 > Android开发

IntentService

2016-07-03 17:05 387 查看
IntentService是Service的子类,因此它不是普通的Service,它比普通的Service增加了额外的功能。

先看Service本身存在的两个问题:

Service不会专门启动一条单独的进程,Service与它所在应用位于同一个进程中。

Service也不是专门一条新的现程,因此不应该在Service中直接处理耗时的任务。

如果开发者需要在Service处理耗时任务,建议在Service中另外启动一条新线程来处理该耗时任务。

那为什么不直接在其它程序组件中启动子线程来处理好时任务呢?

由于Activity可能会被用户退出,BroadcastReceiver的生命周期本身就很短。可能出现的情况是:在子线程还没有结束的情况下,Activity已经被用户退出了,或者BroadcastReceiver已经结束了。在Activity已经退出、BroadcastReceiver已经结束的情况下,此时它们所在的进程就变成了空进程(没有任何活动组件的进程),系统需要内存时可能会优先终止该进程。如果宿主进程被终止,那么该进程内的子线程也会被中止,这样就可能导致子线程无法执行完成。

IntentService正好可以弥补Service的上述两个不足:IntentService将会使用队列来管理请求Intent,每当客户端代码通过Intent请求启动IntentService时,IntentService会将该Intent加入队列中,然后启动一个新的worker线程来处理该Intent。对于异步的startService()请求,IntentService会按次序依次处理队列中的Intent,该线程保证同一时刻只处理一个Intent。由于IntentService使用新的worker线程处理Intent请求,因此IntentService不会阻塞主线程,所以IntentService自己就可以处理耗时任务。

归纳起来,IntentService具有如下特征:

IntentService会创建独立的worker线程来处理所有的Intent请求。

IntentService会创建独立的worker线程来处理onHandleIntent()方法实现的代码,因此开发者无需处理多线程问题。

当所有请求处理完成后,IntentService会自动停止,因此开发者无需调用stopSelf()方法来停止该Service。

为Service的onBind()方法提供了默认实现,默认实现的onBind()方法返回null。

为Service的onStartCommand()方法提供了默认实现,该实现会讲请求Intent添加到队列中。

综上,扩展IntentService实现Service无需重写onBind()、onStartCommand()方法,只需重写onHandleIntent()方法即可。

接下来进行测试,下面是普通Service 直接处理耗时任务:

package com.mystudy.kibi.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

/**
* Created by KIBI熊 on 16/6/28.
*/
public class TestService extends Service{

private long time = System.currentTimeMillis()+20*1000;

@Override
public IBinder onBind(Intent intent) {
Log.e("==>","onBind");
return null;
}

@Override
public void onCreate() {
super.onCreate();
Log.e("==>","onCreate");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("==>","onStartCommand");
while (time > System.currentTimeMillis()){
synchronized (this){
try {
wait(time-System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
Log.e("==>","普通Service结束");
stopSelf();
return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
Log.e("==>","onDestroy");
super.onDestroy();
}

}


IntentService 直接处理耗时任务:

package com.mystudy.kibi.service;

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

/**
* Created by KIBI熊 on 16/7/3.
*/
public class TestIntentService extends IntentService {

private long time = System.currentTimeMillis()+20*1000;

public TestIntentService() {
super("TestIntentService");
Log.e("==>","TestIntentService");
}

@Override
protected void onHandleIntent(Intent intent) {
Log.e("==>","onHandleIntent");
while (time > System.currentTimeMillis()){
synchronized (this){
try {
wait(time-System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
Log.e("==>","IntentService结束");
}
}


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mystudy.kibi.networktype">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

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

<service android:name="com.mystudy.kibi.service.TestService">
<intent-filter>
<action android:name="com.mystudy.kibi.service.TEST_SERVICE" />
</intent-filter>
</service>

<service android:name="com.mystudy.kibi.service.TestIntentService"/>

</application>

</manifest>


Activity界面中含有两个按钮,分别启动上面的普通Service和IntentService。

package com.mystudy.kibi.networktype;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.mystudy.kibi.service.TestIntentService;
import com.mystudy.kibi.service.TestService;

public class MainActivity extends AppCompatActivity {

private Button serviceBtn,intentserviceBtn;
private Intent serviceIntent,intentserviceIntent;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

initData();
initView();
initListener();

}

private void initView(){
serviceBtn = (Button) findViewById(R.id.service_btn);
intentserviceBtn = (Button) findViewById(R.id.intentservice_btn);
}

private void initListener(){
serviceBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(serviceIntent);
}
});
intentserviceBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(intentserviceIntent);
}
});
}

private void initData(){
serviceIntent = new Intent(this,TestService.class);
intentserviceIntent = new Intent(this, TestIntentService.class);
}

}


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
tools:context="com.mystudy.kibi.networktype.MainActivity">

<Button
android:layout_marginTop="50dp"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="service"
android:textColor="#888"
android:id="@+id/service_btn" />

<Button
android:layout_marginTop="50dp"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="intentservice"
android:textColor="#888"
android:id="@+id/intentservice_btn" />

</LinearLayout>


运行结果:

07-03 16:34:29.135 30949-30949/com.mystudy.kibi.networktype E/==>: onCreate
07-03 16:34:29.135 30949-30949/com.mystudy.kibi.networktype E/==>: onStartCommand
07-03 16:34:49.136 30949-30949/com.mystudy.kibi.networktype E/==>: 普通Service结束
07-03 16:34:49.142 30949-30949/com.mystudy.kibi.networktype E/==>: onDestroy
07-03 16:34:49.160 30949-30949/com.mystudy.kibi.networktype E/==>: TestIntentService
07-03 16:34:49.173 30949-31756/com.mystudy.kibi.networktype E/==>: onHandleIntent
07-03 16:35:09.160 30949-31756/com.mystudy.kibi.networktype E/==>: IntentService结束


运行现象:

启动普通Service,可以发现界面处于卡死状态,并会给出ANR(Application Nor Responding)提示,即阻塞了前台的UI线程。

启动TestIntentService,并不会出现上述情况,即不会阻塞前台的UI线程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android