service组件一之创建service
service可以看成一个组件,可以与其他组件如activity绑定。有两种启动方式:
1.通过调用startService()
2.通过调用bindService()
但是这两种方式并不矛盾,可以同时使用。需要注意的是,service运行在程序的所在的进程的主线程中,自己并不会开启一个新的线程,因而为了避免ANR无响应,service中做的操作都要另起一个线程来执行。service可以被其他应用调用。
继承service最好实现以下四个方法:
1.onStartCommand()
2.onBind()
3.onCreate()
4.onDestroy() 可以在该方法中回收service所占资源如关闭线程、注销监听器等。
创建service步骤:
1.继承service类或者IntentService类
二者的区别:service是直接运行在application所在进程的主线程中,因而就必须另起线程来执行任务。但是该方式适合多线程,也即任务请求并非一开始的时候就已经发送到service。
IntentService会新建一个worker线程负责接收所有发送到onStartCommand的intent,并且放入一工作队列中。一次从工作队列中取一个
发送过来的请求,交给onHandleIntent()来处理,因而,业务处理工作可以直接放在该方法中执行。只需要实现一个构造方法和和onHandlerIntent()。这中方式是通过startService()发送请求过来,在某个activity中调用,一次处理一个请求,适合单线程的情况。
2.在manifest.xml中声明新建的service
<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
<activity android:name=".DialogActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name=".TestService"></service>
</application>
3.方式一:若继承IntentService类
类TestIntentService代码如下:
package com.nankang.example.ad.apis;
import android.app.IntentService;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class TestIntentService extends IntentService {
private Bundle bundle;
private String sname ;
private String xname ="xx";
public TestIntentService(String name) {
super(name);
sname= name;
}
public TestIntentService() {
super("xx");
xname= "xxs";
}
@Override
public int onStartCommand(Intent intent,int flags,int startId){
bundle = intent.getExtras();
Toast.makeText(this, bundle.getString("info")+":"+sname+":"+xname, Toast.LENGTH_LONG).show();
return super.onStartCommand(intent, flags, startId);
}
@Override
protected void onHandleIntent(Intent intent) {
//一般默认工作在该方法中执行
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis()+5*1000;
while(endTime>System.currentTimeMillis()){
synchronized (this) {
try {
//等待5秒
wait(endTime-System.currentTimeMillis());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.e("实际执行时间:", String.valueOf(System.currentTimeMillis()-startTime));
}
}
}
}
在activity DialogActivity中调用:
Intent intent = new Intent();
intent.setClass(DialogActivity.this, TestService.class);
Bundle bundle = new Bundle();
bundle.putString("info", "我是从activity来的消息");
intent.putExtras(bundle);
startService(intent);
其中需要注意的是:startService默认调用的是TestService的无参构造方法,若未重写该构造方法,则会报“Unable to instantiate service ”错误。
“That's all you need: a constructor and an implementation of onHandleIntent().” service一旦启动后如何与其他组件或者线程进行通信?还在学习中。。。
4.方式二:继承service类
类TestService代码如下:
package com.nankang.example.ad.apis;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.util.Log;
import android.widget.Toast;
public class TestService extends Service{
private MessageHandler msgHandler;
private Looper looper ;
@Override
public void onCreate(){
HandlerThread thread = new HandlerThread("TestService", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
looper = thread.getLooper();
msgHandler = new MessageHandler(looper);
}
@Override
public int onStartCommand(Intent intent,int flags ,int startId){
Bundle bundle = intent.getExtras();
Toast.makeText(this, bundle.getString("info"), Toast.LENGTH_LONG).show();
Message msg = new Message();
msg.setData(null);
msgHandler.sendMessage(msg);
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private final class MessageHandler extends Handler{
public MessageHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg){
//一般默认工作在该方法中执行
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis()+5*1000;
while(endTime>System.currentTimeMillis()){
synchronized (this) {
try {
//等待5秒
wait(endTime-System.currentTimeMillis());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.e("实际执行时间:", String.valueOf(System.currentTimeMillis()-startTime));
}
}
Log.e("当前线程:",Thread.currentThread().getName());
//stopSelf();
stopSelf(msg.arg1);
}
}
}
类DialogActivity代码类似。
分析执行过程:a).第一次调用service的时候service组件本身有个判断,判断当前service是否存在。第一次会调用onCreate()方法,再往后只要未停止service,不会再调用service的onCreate().
b).每次其他组件调用startService()时,会自动转向service 的onStartCommand()方法,由该方法进行处理,此时,若Service每次都是新建的,则每次都是不同的线程来处理请求。在onStartCommand()将取得的数据包装到message中通过sendMessage,请求的处理可以让线程在handlerMessage中独立进行。
c).停止线程时,可以调用stopSelf()和stopSelf(int)。有可能存在这种情况:当前线程任务已经执行完毕,准备关闭service,此时又有新的请求发送过来,会连新请求的service一起关闭。因此调用stopSelf(int),来关闭当前的service即可。参数为onStartCommand中的startId.
最后service的声明周期如下图(from dev guide):

Figure 1. The service lifecycle. 左边的是由startService()创建,右边的是由bindService()创建

浙公网安备 33010602011771号