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 直接处理耗时任务:
IntentService 直接处理耗时任务:
AndroidManifest.xml
Activity界面中含有两个按钮,分别启动上面的普通Service和IntentService。
activity_main.xml
运行结果:
运行现象:
启动普通Service,可以发现界面处于卡死状态,并会给出ANR(Application Nor Responding)提示,即阻塞了前台的UI线程。
启动TestIntentService,并不会出现上述情况,即不会阻塞前台的UI线程。
先看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线程。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories