写给初学者18_android_四大组件_Service
2017-04-19 17:15
387 查看
安卓18_四大组件-Service
如果说Activity是花枝招展的门面担当,那么Service就是辛勤的后台人员,并且Service是没有可视化界面的。需要注意的是Service也是组件,所以也是运行在主线程当中的,也就意味着不能执行耗时操作,虽然是运行在后台。如果要进行耗时操作,那么需要开启线程。系统在内存紧张的时候会杀死一些优先级比较低的Activity,不过Service的默认优先级是高于Activity的。这样Service被杀死的几率就会比较小,并且有的Service杀死以后还可以再启动起来。
简单的举个例子,如果我使用Activity去播放音乐那么,当Activity不可见以后,却正在播放音乐怎么办,倘若系统一个需要内存,杀死当前的Activity怎么办,这样做的话,那安卓是真的没可能好用的。使用Service来进行音乐的播放,我们也就不会担心Activity的可见与否,以为它完全在后台运行。只不过要注意的是两者之间的通信。
官方定义
Service 是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。主要能完成的事情
例如,服务可以处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序交互,而所有这一切均可在后台进行。Service的类型
本地服务 Local Service
范围:单个应用程序内部案例:基本的一些耗时操作,比如下载。
远程服务 Remote Sercie
范围:几个应用程序之间,但是不能跨手机。案例:比如有一个应用已经用服务的方式去做了多天气的获取,那么其他的应用就可以不用在开启这样的事情,直接去调用就好了。
Service的启动方式
start启动方式 非绑定式
特点:启动服务以后,和启动源不会有任何的关系,启动源无法获取到服务对象、代码实现
1:写一个类继承自Service,Service是一个抽象类,当中有一个onBind需要我们实现,但是我们start的启动方式是可以不管这个方法的。
public class DemoService extends Service { @Override public void onCreate() { super.onCreate(); Log.i("Service-life", "onCreate()"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("Service-life", "onStartCommand()"); return super.onStart bb8a Command(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.i("Service-life", "onDestroy()"); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. Log.i("Service-life", "onBind()"); throw new UnsupportedOperationException("Not yet implemented"); } }
2.在相应的组件中开启Service,开启服务是通过意图Intent,这里和Activity的启动是非常相似的,只不过叫startService();
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button btnStart; private Button btnStop; private Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); intent = new Intent(this, DemoService.class); } private void initView() { btnStart = (Button) findViewById(R.id.btnStart); btnStop = (Button) findViewById(R.id.btnStop); btnStart.setOnClickListener(this); btnStop.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnStart: // 开启 startService(intent); break; case R.id.btnStop: // 停止 stopService(intent); break; } } }
3.根据代码简单测试一下,这里在Service当中,我们将生命周期中回掉的方法都实现了一下。并且使用按钮来简单测试一下。
简单总结:
1.整个过程中,只有调用停止以后service对象才会销毁。
2.没有销毁的情况下,service是可以重启的。
3.onBind在这种启动模式下,并未回调到。
也可以很好的理解Service的生命周期图
注意
很显然这种启动方式是左边的这幅生命周期。但是明显可以感受到,服务启动以后,在运行的整个过程中,我们都无法获得Service对象,并且对其控制。bind启动方式
特点:通过Ibinder接口实例,返回一个ServiceConnection对象,通过该对象的相关方法可以得到Service的对象,从而进行控制。最基本的代码实现:
Service类
public class BindDemoService extends Service {
@Override public void onCreate() { super.onCreate(); Log.i("Service-life", "onCreate()"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("Service-life", "onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.i("Service-life", "onDestroy()"); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. Log.i("Service-life", "onBind()"); return null; } @Override public void unbindService(ServiceConnection conn) { super.unbindService(conn); Log.i("Service-life", "unbindService()"); } }
主要看的是onBind和upbindService
Activity中
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button btnStart; private Button btnStop; private Intent intentStart,intentBind; private Button btnBind; private Button btnUnbind; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); intentStart = new Intent(this, DemoService.class); intentBind = new Intent(this,BindDemoService.class); } private void initView() { btnStart = (Button) findViewById(R.id.btnStart); btnStop = (Button) findViewById(R.id.btnStop); btnBind = (Button) findViewById(R.id.btnBind); btnUnbind = (Button) findViewById(R.id.btnUnbind); btnStart.setOnClickListener(this); btnStop.setOnClickListener(this); btnBind.setOnClickListener(this); btnUnbind.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnStart: // 开启 startService(intentStart); break; case R.id.btnStop: // 停止 stopService(intentStart); break; case R.id.btnBind: //绑定 bindService(intentBind,null, Service.BIND_AUTO_CREATE); break; case R.id.btnUnbind: //解绑 unbindService(null); break; } } @Override protected void onDestroy() { super.onDestroy(); } }
这对bindService的最后一个参数做一个说明:
1).Context.BIND_AUTO_CREATE
说明:表示收到绑定请求的时候,如果服务尚未创建,则即刻创建,在系统内存不足需要先摧毁优先级组件来释放内存,且只有驻留该服务的进程成为被摧毁对象时,服务才被摧毁
2).Context.BIND_DEBUG_UNBIND
说明:通常用于调试场景中判断绑定的服务是否正确,但容易引起内存泄漏,因此非调试目的的时候不建议使用
3).Context.BIND_NOT_FOREGROUND
说明:表示系统将阻止驻留该服务的进程具有前台优先级,仅在后台运行,该标志位位于Froyo中引入。
结果
注意
可以看到onBind()方法被回调,当然我们在这里对第二个参数采用了空处理,第三个参数下面再来解释,但是可以发现Service和我们的Activity已经形成了绑定,当我绑定开启了一个服务以后,退出Activity时并没有解绑,就会出现途中的错误。同样道理,我如若没有绑定一个服务就开始解绑,或者解绑多次,同样也是会出错的。通过ServiceConnection进行创建,并且获取到Service对象
Service类中public class BindDemoService extends Service { private MyBinder myBinder = new MyBinder(); @Override public void onCreate() { super.onCreate(); Log.i("Service-life", "onCreate()"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("Service-life", "onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.i("Service-life", "onDestroy()"); } public class MyBinder extends Binder{ // 定义相关方法 /* 一个返回当前Service对象的方法 */ public BindDemoService getServie(){ return BindDemoService.this;// 内部类访问外部类的对象 } } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. Log.i("Service-life", "onBind()"); return myBinder; } @Override public void unbindService(ServiceConnection conn) { super.unbindService(conn); Log.i("Service-life", "unbindService()"); } public void play(){ Log.i("Service-life", "play()-播放"); } public void stop(){ Log.i("Service-life", "stop()-停止"); }public void next(){ Log.i("Service-life", "next()-下一首"); } public void previous(){ Log.i("Service-life", "previous()-上一首"); } }
注意
这里需要实现Binder并且在Binder当中我们可以做不少的事情,比如返回当前的Service对象。Activity中:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button btnStart; private Button btnStop; private Intent intentStart, intentBind; private Button btnBind; private Button btnUnbind; private BindDemoService bindDemoService; // ServiceConnection对象 private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder binder) { // Service连接时回调binder就是我们在onBind当中返回的binder BindDemoService.MyBinder myBinder = (BindDemoService.MyBinder) binder; bindDemoService = myBinder.getServie(); } @Override public void onServiceDisconnected(ComponentName name) { } }; private Button btnPlay; private Button btnStopPlay; private Button btnNext; private Button btnPrevious; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); intentStart = new Intent(this, DemoService.class); intentBind = new Intent(this, BindDemoService.class); } private void initView() { btnStart = (Button) findViewById(R.id.btnStart); btnStop = (Button) findViewById(R.id.btnStop); btnBind = (Button) findViewById(R.id.btnBind); btnUnbind = (Button) findViewById(R.id.btnUnbind); btnPlay = (Button) findViewById(R.id.btnPlay); btnStopPlay = (Button) findViewById(R.id.btnStopPlay); btnNext = (Button) findViewById(R.id.btnNext); btnPrevious = (Button) findViewById(R.id.btnPrevious); btnStart.setOnClickListener(this); btnStop.setOnClickListener(this); btnBind.setOnClickListener(this); btnUnbind.setOnClickListener(this); btnPlay.setOnClickListener(this); btnStopPlay.setOnClickListener(this); btnNext.setOnClickListener(this); btnPrevious.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnStart: // 开启 startService(intentStart); break; case R.id.btnStop: // 停止 stopService(intentStart); break; case R.id.btnBind: bindService(intentBind, connection, Service.BIND_AUTO_CREATE); break; case R.id.btnUnbind: unbindService(connection); break; case R.id.btnPlay: bindDemoService.play(); break; case R.id.btnStopPlay: bindDemoService.stop(); break; case R.id.btnNext: bindDemoService.next(); break; case R.id.btnPrevious: bindDemoService.previous(); break; } } @Override protected void onDestroy() { super.onDestroy(); } }
注意一下Service对象的获取方式
这里只是一个简单的模拟,当然对于Service初学者没有必要掌握的这么深,也不必要非要搞清楚Binder这个类到底是如何在做通信,基本的使用会了再去做深入的研究
相关文章推荐
- 写给初学者20_android_四大组件_BroadCastReciver
- Android四大组件之 Service
- 01 Android应用的构成 四大组件 Activity, Intent Receiver , Service , Content Provider
- Android学习笔记39:Android四大组件之Service
- Android 四大组件(Activity、Service、BroadCastReceiver、ContentProvider)
- Java乔晓松-android的四大组件之一Service(服务的绑定)
- Android四大组件之 Service
- Android:四大组件之一service小结
- Android开发四大组件---Service详解
- android四大组件之一Service的startService()与bindService()区别?
- Android 四大组件(Activity、Service、BroadCastReceiver、ContentProvider)
- android 编写Service(四大组件之一)的方法
- Android学习笔记(2)————Android四大组件之二(Service )
- Android四大组件之一Service(服务)
- Android应用程序四大组件之Service(一)
- 01 Android应用的构成 四大组件 Activity, Intent Receiver , Service , Content Provider
- Android四大组件——Service 生命周期详解
- android四大组件之Service
- Java乔晓松-android的四大组件之一Service(服务的绑定)
- android四大组件之Service