1. android中什么是service
service是四大组件之一,是一种计算型组件,在后台一直执行,直到调用stopSelf()或者stopService(),用户感知不到,但是它任然是运行在主线程,做耗时操作的时候还是需要开辟子线程。IntentService是Service的改良,它自动运行在子线程,而且会自动关闭。
2. 如何开启一个服务
开启服务有两种方式,都是去新建类并继承Service,别忘了在清单文件注册。以下是两种方式Service的生命周期。
1. onCreate onStartCommand onDestroy 普通模式。
onCreate 只是在第一次创建时会调用,以后每次开启服务,都只会走onStartCommand。
Intent intent=newIntent(this,MyService.class);
startService(intent);//开启服务
stopService(intent);//关闭服务
2. onCreate onBind onUnBind onDestroy 绑定模式用于和宿主Activity进行交流。
public class MyService extends Service {
MyBinder myBinder = new MyBinder();
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
class MyBinder extends Binder {
public void add() {
}
public void remove() {
}
}
}
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,MyService.class);
bindService(intent,connection,BIND_AUTO_CREATE);
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
MyService.MyBinder binder = (MyService.MyBinder)iBinder;
binder.add();
binder.remove();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
}
如果你同时使用了第一种方式开启服务,还绑定了服务,那么你一定要同时调用stopService()和unbindService()方法,onDestroy方法才会执行。
3. 前台服务
前台服务的优先级比一般服务高,一般不会被系统杀死。一旦开启后类似于通知效果在通知栏显示。
在服务的onStartCommand中调用此方法就将当前服务变成前台服务
private void showNotification() {
CharSequence text = getText(R.string.local_service_started);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, LocalServiceActivities.Controller.class), 0);
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.stat_sample) // the status icon
.setTicker(text) // the status text
.setWhen(System.currentTimeMillis()) // the time stamp
.setContentTitle(getText(R.string.local_service_label)) // the label of the entry
.setContentText(text) // the contents of the entry
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
.build();
startForeground(1, NOTIFICATION);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy()");
stopForeground(true);// 停止前台服务--参数:表示是否移除之前的通知
super.onDestroy();
}
4. HandlerThread
HandlerThread继承自Thread,实际上就一个Thread,只不过它比普通的Thread多了一个Looper和一个MessageQueue,对外提供自己这个Looper对象的get方法,然后创建Handler时将HandlerThread中的looper对象传入。
不要忘记创建HandlerThread时必须调用其start()方法。
HandlerThread中只有一个消息队列,消息顺序执行,因此可能会阻塞任务。
但是需要注意的是,当activity退出了,这个HandlerThread线程并没有终止,还是在那里做looper死循环,这样随着activity的创建和退出的次数增多,这样占用系统资源的无用线程会越来越多,因此在明确不需要使用HandlerThread时,可通过quit()或者quitSafely()来终止线程执行。
HandlerThread的简单使用
HandlerThread handlerThread = new HandlerThread("新线程");
handlerThread.start(); //创建HandlerThread后一定要记得start()
Handler handler = new Handler(handlerThread.getLooper()){
//重写handleMessage方法处理消息
//通过handler在外部send或者post消息,就会在子线程中处理该消息 @Override
public void handleMessage(Message msg) {
super.handleMessage(msg); //处理消息
}
};
HandlerThread的优点
如果多次使用new Thread(){...}.start()这种方式开启一个子线程,会创建多个匿名线程,降低程序执行性能。而HandlerThread是Looper的,这样便可以通过消息来多次重复使用该线程,节省开支。
5. IntentService
IntentService之前讲到过,它与普通的服务的开启方式一致,但是它具有在子线程运行,执行完自动关闭的特点。逻辑都在onHandleIntent中操作。它的内部实现是HandlerThread和Handler。
多个后台任务同时存在时,因为Looper是顺序处理消息的,所以IntentService会按照发起任务顺序排队执行。
以下两个方法构造方法和onHandleIntent是必须实现的
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
}
}
6. 如何保证服务不被杀死
1. 提高服务优先级
2. 提高服务所在进程优先级
3. 在onStartCommand 中返回START_STICKY