“山中习静观朝槿,松下清斋折露葵。”
学习是一个持续渐进的过程,让我们用代码书写人生。
上一章节我对Android四大组件之一Service知识点进行了初步的总结,这一章节我进行对service的启动方式之一StartService进行代码示例。
一、生命周期
- onCreate:如果多次执行了Context的startService方法启动Service,Service方法的onCreate方法只会在第一次创建Service的时候调用一次,以后均不会再次调用。我们可以在onCreate方法中完成一些Service初始化相关的操作
- onStartCommand:如果多次执行了Context的startService方法,那么Service的onStartCommand方法也会相应的多次调用。onStartCommand方法很重要,我们在该方法中根据传入的Intent参数进行实际的操作,比如会在此处创建一个线程用于下载数据或播放音乐等
- onBind:Service中的onBind方法是个抽象方法,所以Service类本身就是一个抽象类,也就是说onBind方法必须要重写,即使用不到。通过startService使用Service时,我们在重写onBind方法时,只需要将其返回值设为null即可。onBind方法主要是用于给bindService方法调用Service时才使用到。
- onDestiny:Service销毁时回调函数
- 通过上面,我们可以把Service生命周期归纳成下面情况
Activity界面的代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btnStart;
private Button btnStop;
private boolean isStopService = false;//判断服务是否开启的标志
private Intent intent = null;
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
startService(intent);
handler.sendEmptyMessageDelayed(0,1000);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); // 隐藏标题栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); // 隐藏状态栏
setContentView(R.layout.activity_main);
initView();
initData();
}
//初始化控件
private void initView() {
btnStart = (Button) findViewById(R.id.btn_start);
btnStop = (Button) findViewById(R.id.btn_stop);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
}
//初始化数据intent
private void initData() {
intent = new Intent(this, TestStartService.class);//设置一个跳转到服务的意图
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
isStopService = true;
//定时器
handler.sendEmptyMessageDelayed(0,1000);
// startService(intent);
break;
case R.id.btn_stop:
if (intent != null && isStopService) {
Log.v("test", "停止服务");
stopService(intent);
}
break;
}
}
}
Service界面的代码:
public class TestStartService extends Service {
@Override
public void onCreate() {//创建service
super.onCreate();
Log.v("test","onCreate");
}
@Override
public IBinder onBind(Intent intent) {//数据获取
return null;
}
/**
* @param intent
* @param flags 官方解释:有关此开始请求的附加数据。目前是0
* @param startId 官方解释:一个唯一的整数,代表这个特定的请求开始
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {//启动服务
Log.v("test","startId="+startId);
if (startId == 8){
stopSelf();
}
return START_REDELIVER_INTENT;
}
@Override
public void onDestroy() {//销毁服务
super.onDestroy();
}
}
二、onStartCommand中返回值
- 常用的返回值有:START_NOT_STICKY、START_SICKY和START_REDELIVER_INTENT,这三个都是静态常理值。
- START_NOT_STICKY:表示当Service运行的进程被Android系统强制杀掉之后,不会重新创建该Service,如果想重新实例化该Service,就必须重新调用startService来启动。
- 使用场景:表示当Service在执行工作中被中断几次无关紧要或者对Android内存紧张的情况下需要被杀掉且不会立即重新创建这种行为也可接受的话,这是可以在onStartCommand返回值中设置该值。如在Service中定时从服务器中获取最新数据
- START_STICKY:表示Service运行的进程被Android系统强制杀掉之后,Android系统会将该Service依然设置为started状态(即运行状态),但是不再保存onStartCommand方法传入的intent对象,然后Android系统会尝试再次重新创建该Service,并执行onStartCommand回调方法,这时onStartCommand回调方法的Intent参数为null,也就是onStartCommand方法虽然会执行但是获取不到intent信息。
- 使用场景:如果你的Service可以在任意时刻运行或结束都没什么问题,而且不需要intent信息,那么就可以在onStartCommand方法中返回START_STICKY,比如一个用来播放背景音乐功能的Service就适合返回该值。
- START_REDELIVER_INTENT:表示Service运行的进程被Android系统强制杀掉之后,与返回START_STICKY的情况类似,Android系统会将再次重新创建该Service,并执行onStartCommand回调方法,但是不同的是,Android系统会再次将Service在被杀掉之前最后一次传入onStartCommand方法中的Intent再次保留下来并再次传入到重新创建后的Service的onStartCommand方法中,这样我们就能读取到intent参数。
- 使用场景:如果我们的Service需要依赖具体的Intent才能运行(需要从Intent中读取相关数据信息等),并且在强制销毁后有必要重新创建运行,那么这样的Service就适合返回START_REDELIVER_INTENT。