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

Android中服务(Service)的的生命周期,两种开启服务的方式的不同点,Service与Activity之间的通讯

2016-10-18 15:14 615 查看
工作内容:

1.Service的生命周期(bindService,startService的区别)

2.Service与Activity之间的通讯方式

学习分享:

准备:定义服务类继承自Service,在manifests中注册如下:(注册在application中与activity并列)

<service android:name=".MyService">
</service>


自定义服务类

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import org.greenrobot.eventbus.EventBus;

public class MyService extends Service {
private MyBinder myBinder;
public boolean isGo = true;
private EventBus eventBus;
private int x= 0;
@Nullable
@Override
public IBinder onBind(Intent intent) {
LogD.d("onBind");
myBinder = new MyBinder();
return myBinder;
}
//Android 2.2之后已被摒弃,建议使用onStartCommand
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
LogD.d("onStart");
}

@Override
public void onCreate() {
super.onCreate();
LogD.d("onCreate");
eventBus =EventBus.getDefault();//初始化EventBus
Intent intent = new Intent(this,SecoundActivity.class);
PendingIntent pendIntent = PendingIntent.getActivity(this,0,intent,0);
Notification noti = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("前台服务通知")
.setContentText("点击跳转懂啊页面二")
.setContentIntent(pendIntent)
.build();
startForeground(1,noti);//创建前台Service(在通知栏显示)
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogD.d("onStartCommand");
/**
* 正常情况下我们会在这里开启一条子线程来执行任务
* 执行线程——Ui主线程
*/
new Thread(){
@Override
public void run() {
while (isGo){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
LogD.d("onStartCommand"+x++);
}
/**
* 在执行完之后这里使用了EventBus来将执行完毕的消息发送到Activity中
* 由此可想而知,也可以使用接口回调的方式来传递信息到Activity中,
* 但是要注意的是这里执行的是后台线程
*/
eventBus.post(new ServiceEvent("onStartCommand执行完毕"));
}
}.start();
return super.onStartCommand(intent, flags, startId);
}

@Override
public boolean onUnbind(Intent intent) {
LogD.d("onUnbind");
return super.onUnbind(intent);
}

@Override
public void onDestroy() {
LogD.d("onDestroy");
isGo =  false;
super.onDestroy();
}
class MyBinder extends Binder {

public void startDownload() {
LogD.d("执行Bindder类中的startDownload()");
/**
* 可以在这里开线程执行bandService的任务
* 执行线程——Ui主线程
*/
new Thread(){
@Override
public void run() {
super.run();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
LogD.d("startDownload:"+i);
}
eventBus.post(new ServiceEvent("startDownload执行完毕"));
}
}.start();
}

}
}
Activity.java代码
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button btnStart,btnStop,btnBind,btnUnBind;
private MyService.MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
btnStart = (Button) findViewById(R.id.button);
btnStop = (Button) findViewById(R.id.button2);
btnBind = (Button) findViewById(R.id.button3);
btnUnBind = (Button) findViewById(R.id.button4);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
btnBind.setOnClickListener(this);
btnUnBind.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button:
//点击事件——触发开启服务
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.button2:
//点击事件——触发停止服务
Intent startIntent1 = new Intent(this, MyService.class);
stopService(startIntent1);
break;
case R.id.button3:
//点击事件——触发绑定服务
Intent startIntent2 = new Intent(this, MyService.class);
bindService(startIntent2, connection, Service.BIND_AUTO_CREATE);
break;
case R.id.button4://【应当用一个标识符来确定是否存在已绑定服务】【不判断——连续解绑会出错】
//点击事件——取消绑定服务
if(connection!=null&&myBinder!=null){
Intent startIntent3 = new Intent(this, MyService.class);
unbindService(connection);
}else{
Toast.makeText(this,"已经不存在绑定",Toast.LENGTH_SHORT).show();
}

break;
}
}
private ServiceConnection connection = new ServiceConnection() {

@Override
public void onServiceDisconnected(ComponentName name) {
//取消绑定时调用
}

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//绑定时掉用
myBinder = (MyService.MyBinder) service;
myBinder.startDownload();
}
};
//接收Service中通过EventBus传过来的消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void showMsg(ServiceEvent event){
Toast.makeText(this,event.getMsg(),Toast.LENGTH_SHORT).show();
}

@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}


一、Service的生命周期(bindService,startService的区别)

1.开启方式:startService

//点击事件——触发开启服务
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
.....
.....
//点击事件——触发停止服务
Intent startIntent1 = new Intent(this, MyService.class);
stopService(startIntent1);


执行生命周期:


注意:在onCreate之后重复点击开启Service,会重复执行onStartCommand,onStart方法,不会重复执行onCreate【注:onStart方法已被onStartCommand方法取代,不建议使用】

2.开启方式:bindService

private ServiceConnection connection = new ServiceConnection() {//绑定需传入ServiceConnection实现类

@Override
public void onServiceDisconnected(ComponentName name) {//取消绑定时调用
}

@Override
public void onServiceConnected(ComponentName name, IBinder service) {//绑定时调用
myBinder = (MyService.MyBinder) service;
myBinder.startDownload();
}
};
....
....
//点击事件——触发绑定服务
Intent startIntent2 = new Intent(this, MyService.class);
bindService(startIntent2, connection, Service.BIND_AUTO_CREATE);
....
....
//点击事件——取消绑定服务
if(connection!=null&&myBinder!=null){
Intent startIntent3 = new Intent(this, MyService.class);
unbindService(connection);
}else{
Toast.makeText(this,"已经不存在绑定",Toast.LENGTH_SHORT).show();
}
执行生命周期:


注意:重复点击触发绑定事件并不会重复执行onBind方法

另外:

1.bindService和startService可以交叉使用,两者都使用,则需调用unbindService方法和stopService方法才会终止服务

2.无论开启多少次同一个Service,只需执行一次stopService/unbindService方法即可终止这个服务

3.我们应当在starService时就准备好在哪里stopService,在bindService时就准备好在那里unbindService

二、Service与Activity之间的通讯方式

1.在上方的bindService中可以发现我绑定之后会执行Bingdder类中的startDownload方法,这就实现了Activity中调用Service中的方法

2.我们也可以通过控制Service的生命周期的方式来实现简单的信息传递(本例中是控制Service的执行线程的isGo的值来终止其子线程继续执行)

3.可以在Service执行任务过程中通过EventBus.post()来将执行中的数据传送到Activity中(上面代码已经贴出)(EventBus需添加依赖/导包)

4.也可以使用回调的方式来将Service中执行任务的数据传送的Activity中(回调就不多说了,前面的章节有详细介绍)

执行效果:

执行线路1:【不调用stopService,即使退出app,服务也将继续执行】

点击执行startService——执行onCreate,onStartCommand(开始执行子线程[记数输出Log]),onStart;

点击执行stopService——执行onDestory(isGo=false),子线程接收到isGo=false之后终止执行——执行Activity中的showMsg方法;

执行线路2:【随着Activity生命周期结束而结束】

点击执行bindService——执行onCreate,onBind——执行Activity中的connection对象的onServiceConnected方法——执行Service中Binder子类的startDownload方法,执行子线程【应该用一个标识(boolean之类)来标识是否已在Activity中绑定了服务,不存在——不解绑,存在——解绑】

点击执行unbindService——执行onUnbind,onDestory

执行路线3:(请自行研究...)

点击执行startService

点击执行bindService

点击执行stopService

点击执行unbindService

三、实现在前台进程执行Service

由于后台Service可能会因为内存不足被系统回收,就可以创建前台Service主要是将Service显示在通知栏中

代码在上面的Servie中已经存在了,并注释(需要先会Notification的使用),这里只是简单实现了一个跳转,点击通知栏条跳转到app中的页面2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: