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

Android菜鸟学步之Service

2016-07-05 10:17 309 查看

Service

Service
的创建:

在Java文件的包名处右键新建一个Service,默认勾选enable和exported,然后finish就可以了。

然后我们打开AndroidManifest,就可以看到多出了以下内容:

<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
</service>


由于以前没基本用过Service,所以我就详细些一下过程。

public class MyService extends Service {
public MyService() {

}

@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {//这一块用来可以执行想要执行的代码
new Thread(){
@Override
public void run() {
super.run();
while (true) {
System.out.println("服务正在运行....");
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
return super.onStartCommand(intent, flags, startId);

}
}


我们在
MainActivity
里面也要进行设置,

findViewById(R.id.btnStartService).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startService(new Intent(MainActivity.this,MyService.class));
}
});


这个其实跟前面启动一个
Activity
的方法是一样的,

然后我们再写一个关闭服务的,

findViewById(R.id.btnStopService).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
stopService(intent);
}
});


到这里我们发现关闭服务方法基本上和开启服务还是一样的嘛!之不符哦一个是startService一个是
stopService
,千万不要写成
start/stop Activity
哦,这里不是
Activity
而是
Service
啦,我写的时候就习惯性的写成了
Activity
,然后点击启动服务的时候,出现了错误。

前面在服务中执行的代码我们开启了一个Thread线程,那我们直接输出可不可以呢?当然可以了。

绑定Service

为了了解整体,下面贴出MainActivity的全部代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {
private  Intent intent;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent=new Intent(MainActivity.this,MyService.class);

findViewById(R.id.btnStartService).setOnClickListener(this);//这样写看起来简洁很多,要实现OnClickListener接口
findViewById(R.id.btnStopService).setOnClickListener(this);
findViewById(R.id.btnBindService).setOnClickListener(this);
findViewById(R.id.btnUnbindService).setOnClickListener(this);
}

@Override
public void onClick(View view) {//平时很少用switch,这里也算是复习一下
switch (view.getId()){
case R.id.btnStartService:
startService(intent);
break;                  //不要忘记break
case R.id.btnStopService:
stopService(intent);
break;
case R.id.btnBindService:
bindService(intent,this, Context.BIND_AUTO_CREATE);//这里的this要实现ConnetionService接口
break;
case R.id.btnUnbindService:
unbindService(this);
break;
}
}

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
System.out.println("service connected..");
}

@Override
public void onServiceDisconnected(ComponentName componentName) {

}
}


在MyService里面基本没有多大变化

public class MyService extends Service {
public MyService() {

}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return  new Binder();//这里要替换一下了,不能再throw exception了
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

new Thread(){
@Override
public void run() {
super.run();
while (true){
System.out.println("服务正在进行...");
try {
sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
return super.onStartCommand(intent, flags, startId);

}
}


发现这里有一个问题,实际我在运行的时候,点击启动服务,一直会输出服务正在进行…但是我点击停止服务的时候,还继续输出,这是为什么呢?

那么我尝试着解决这个问题,现在我点击的是停止服务,代码中实现的也是stopService(intent),可是正在运行的代码不是属于停止服务的,我们要停止的其实是下面的这个方法:

@Override
public void onDestroy() {
super.onDestroy();
System.out.println("service destroyed");//这一句是我添用来测试的
}


我把上面的这一段代码添加之后发现,我们点击停止服务的时候,实际上会输出service destroyed,也就是我们要输出的内容,但是这个说明上面呢?说明点击按钮后执行到了
onDestroy()
,而onStartCommand方法还在一直进行,那么问题又来了,按理说执行到了
onDestroy()
不就应该结束了吗?那么为什么还会服务还会继续运行呢?

service 生命周期

先来大致看一下Service的生命周期



极客学院的老师讲这个的时候把onStartCommand这部分自定义的内容给注释掉了,所以他的演示中看不到stopService后onStartCommand仍然在运行的情况(这个问题我还是不知道为什么)。下面是我也注释掉之后的情况:

服务的生命周期我们只需要记住有两个:一个是onCreate(),一个是onDestroy();我们重写这两个函数,然后运行

点击启动服务显示:service create

点击结束服务显示:service destroyed

点击绑定服务先后显示:service create service connected..

点击解除绑定服务显示: service destroyed

如果同时点击启动服务和绑定服务,必须同时解除绑定和结束服务,(经过验证,无论是先解除绑定后结束服务还是先结束服务后绑定都是可以的,但是必须两个都要有)。

下面是另外一种情况,我们点击绑定服务,然后直接点击退出,会发现log里面显示报错信息,同时打印了service destroyed,这样就意味着如果我们的Activity与某个Service绑定的话,在这个Activity退出的时候,Service会取消绑定。

继续进行演示:我们在onStartCommand()中写上一句话:System.out.println(“onstartCommand”);然后运行程序看运行顺序(这里会不会解决我前面的问题呢?拭目以待)。

点击启动服务:显示service create,onstartCommand

继续点击启动服务:显示onstartCommand

这说明在我们第一次执行startService的时候执行了onCreate和onStartCommand,之后再执行startService时onCreate就不会再执行了,而onStartCommand每次都会执行。因为一个服务只会创建一次。下面再做一个演示:我们先定义一个布尔变量ServiceRunning,当程序进入到onCreate()的时候我们令他等于true,到结束的时候令他等于false,然后在onStartCommand里面定义当这个布尔变量为true的时候才能运行,那么当我们结束服务的时候onStartCommand里面的程序就会停止运行了。

事实上,经过演示,我发现:我们如果点击绑定服务,那么onStartCommand是不会执行的,它只会在点击启动服务的时候执行。

public class MyService extends Service {

private boolean ServiceRunning=false;
public MyService() {

}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return  new Binder();//这里要替换一下了,不能再throw exception了
}

@Override
public void onCreate() {
ServiceRunning=true;
super.onCreate();
System.out.println("service create");
}

@Override
public void onDestroy() {
super.onDestroy();
System.out.println("service destroyed");
ServiceRunning=false;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

new Thread(){
@Override
public void run() {
super.run();
while (ServiceRunning){
System.out.println("服务正在进行...");
try {
sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
System.out.println("onstartCommand");
return super.onStartCommand(intent, flags, startId);

}
}


这种方法确实是解决了onStartCommand里面的任务在我们结束服务时还在运行的问题,可是问题是,到现在为止我还是不知道onStartCommand()为什么在结束服务的时候还是不能自己停止运行它难道不是服务的一部分吗?服务都终止了,它为什么还可以运行?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android Service