4、Service详解(二):本地Service
来源:互联网 发布:mac显示网络图标 编辑:程序博客网 时间:2024/05/21 07:14
本地Service同Activity一样,会存在于当主前线程中,所以我们不能把耗时的操作放在Service中执行,比如把网络请求处理的任务放到这里面的话,同Activity一样,可会会报ANR问题,这点我们在开发的时候需要注意,官方的API也给出了这样的提示。Service和Activity的最大区别就在于Service没有前台界面,尽管没有界面,他还是有自己的生命周期的。
为了能够演示启动和停止Service,我们使用两个按钮,直接在activity_main.xml中插入2个按钮,分别用于启动Service和停止Service:
界面如图所示
在MainActivity中分别实现启动和停止
所有的准备都完成了,下面我们开始测试:
1.进入应用,我们点击启动按钮,这时LogCat输出了两行信息,正如生命周期所示
Service OnCreate
Service OnStartCommand
2.再次点击启动按钮,LogCat输出了一行信息,说明Service已经有一个实例启动,不会再执行OnCreate
Service OnStartCommand
3.点击停止按钮,LogCat输出一行信息,Service已经停止。
Service OnDestroy
4.再次点击启动按钮,Service再次启动
Service OnCreate
Service OnStartCommand
5.直接点击返回键,退出应用,Logcat没有任何输出,Service仍在后台运行,这个问题一定要注意
6.再次进入应用,点击返回键,LogCat输出一行信息,退出应用没有停止的Service已经停止。
Service OnDestroy
(二)通过bindService()方法启动Service
首先我们先看一下生命周期中的几个方法:
void onCreate()和 void onDestroy()就不说了,上面讲过了看下其他的
• IBinder onBind(Intent intent):该方法是Service子类必须实现的方法,该方法返回一个IBinder对象,应用程序可通过该对象与Service组件通信。
• boolean onUnbind(Intent intent):当该Service上绑定的所有客户端都断开连接时将会回调该方法。
使用startService方式启动的Service与访问者之间基本上不存在关联,因此Service与访问者之间也无法进行通信和数据交换。如果需要访问者和Service进行方法调用和数据交换,则应该使用bindService方法启动和关闭。
使用bindService方式,需要调用Context的bindService(Intent service,ServiceConnection conn,int flags)该方法有三个参数,三个参数都比较重要,下面依次介绍这三个参数:
• service:通过Intent指定要启动的Service
• conn:ServiceConnection对象用于访问者与Service连接情况,当连接成功则回调该对象的onServiceConneccted(ComponentName name,IBinder service)方法,当访问者与Service由于异常情况终止(unBindService断开连接时不回调)连接时会回调该对象的onServiceDisconnected(ComponentName name)方法。
• flags:指定绑定时是否自动创建Service,0为不自动创建,BIND_AUTO_CREATE为自动创建。
我们可以看到Service中的onBind方法会返回一个IBinder对象,于此同时,我们看到bindService中conn参数对应的对象中有个方法onServiceConneccted(ComponentName name,IBinder service),这里面有个参数IBinder service,其实这两个IBinder对戏那个是同一个,而组件与Service的通信也是通过IBinder方式来完成的。通常我们采用继承Binder的方式来实现自己的IBinder对象。
下面我们还是通过例子来看一下bindService方式怎么使用:
首先定义了一个Service组件,我们想要看看组件与Service之间的通信情况,所以我们先定义一个接口,方便数据访问:
来看一下我们的Service,这里要重点看我们自己定义的Binder对象,通信就靠它了:
同样需要在AndroidMenifist中注册:
我们定义一个布局文件activity_bindservice.xml,放上三个按钮,1个绑定按钮,1个解绑定按钮,1个查看通信的按钮:
界面如图所示
所有的准备都完成了,下面我们开始测试:
1.进入应用,我们点击启动按钮,这时LogCat输出了两行信息,正如生命周期所示
Service onCreate
Service onBind
2.点击停止按钮,LogCat输出两行信息,说明已经解除连接,并且停止了Service
Service onUnbind
Service onDestroy
3.再重复执行步骤1,这时候Service已经绑定,我们退出应用,会发现有错误提示,这是由于还没有解除绑定就退出组件了,所以会报错,我们开发过程中要注意解除绑定
4.再重复执行步骤1,点击查看书的名字按钮,会提示:书名:IOS开发,这说明我们成功的通信了。
(三)start和bind方式的区别与注意
1、通过startService()和stopService()启动关闭服务。适用于服务和访问者之间没有交互的情况。如果服务和访问者之间需要方法调用或者传递参数,则需要使用bindService()和unbindService()方法启动关闭服务。
2、采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法,这个时候访问者和服务绑定在一起。
3、如果访问者要与服务进行通信,那么,onBind()方法必须返回Ibinder对象。如果访问者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果访问者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()—>onDestroy()方法。
4、Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又 bindService,Service只被创建一次。如果先是bind了,那么start的时候就直接运行Service的onStart方法,如果先是start,那么bind的时候就直接运行onBind方法。如果你先bind上了,就stop不掉了,只能先UnbindService, 再StopService,所以是先start还是先bind行为是有区别的。
Service生命周期:
如果应用程序通过startService()方法来启动Service,Service的生命周期如上图左边所示。
如果应用程序通过bindService()方法来启动Service,Service的生命周期如上图右边所示。
(一)通过startService()方法启动Service
首先我们先看一下上面生命周期中的几个方法:
• void onCreate();当该Service第一次被创建后将立即回掉该方法。
• void onStartCommand(Intent intent,int flags,int startId);该方法的早期方法是onStart(Intent intent,int startId);每次通过startService(Intent intent)方法启动Service时都会回掉该方法。
• void onDestroy();当该Service被关闭之前会回掉该方法。
下面的类定义了一个Service组件,我们只是输出了一条语句:
public class ServiceWithStart extends Service { @Override public IBinder onBind(Intent intent) { // 使用startService方式不会回调这个方法 return null; } @Override public void onCreate() { System.out.println("Service OnCreate"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("Service OnStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { System.out.println("Service OnDestroy"); super.onDestroy(); }}
<service android:name= ".ServiceWithStart" ></service>
为了能够演示启动和停止Service,我们使用两个按钮,直接在activity_main.xml中插入2个按钮,分别用于启动Service和停止Service:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools" android:layout_width= "match_parent" android:layout_height= "match_parent" android:background= "#fff" android:gravity= "center" android:orientation= "vertical" > <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:onClick="onBtnStartService" android:text="使用StartService启动" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:onClick="onBtnStopService" android:text="使用stop停止" /></LinearLayout>
界面如图所示
在MainActivity中分别实现启动和停止
public class MainActivity extends Activity { private Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout. activity_main); intent = new Intent(this , ServiceWithStart.class ); } //第一个按钮的绑定事件 public void onBtnStartService(View v) { startService( intent); } //第二个按钮的绑定事件 public void onBtnStopService(View v) { stopService( intent); }}
所有的准备都完成了,下面我们开始测试:
1.进入应用,我们点击启动按钮,这时LogCat输出了两行信息,正如生命周期所示
Service OnCreate
Service OnStartCommand
2.再次点击启动按钮,LogCat输出了一行信息,说明Service已经有一个实例启动,不会再执行OnCreate
Service OnStartCommand
3.点击停止按钮,LogCat输出一行信息,Service已经停止。
Service OnDestroy
4.再次点击启动按钮,Service再次启动
Service OnCreate
Service OnStartCommand
5.直接点击返回键,退出应用,Logcat没有任何输出,Service仍在后台运行,这个问题一定要注意
6.再次进入应用,点击返回键,LogCat输出一行信息,退出应用没有停止的Service已经停止。
Service OnDestroy
(二)通过bindService()方法启动Service
首先我们先看一下生命周期中的几个方法:
void onCreate()和 void onDestroy()就不说了,上面讲过了看下其他的
• IBinder onBind(Intent intent):该方法是Service子类必须实现的方法,该方法返回一个IBinder对象,应用程序可通过该对象与Service组件通信。
• boolean onUnbind(Intent intent):当该Service上绑定的所有客户端都断开连接时将会回调该方法。
使用startService方式启动的Service与访问者之间基本上不存在关联,因此Service与访问者之间也无法进行通信和数据交换。如果需要访问者和Service进行方法调用和数据交换,则应该使用bindService方法启动和关闭。
使用bindService方式,需要调用Context的bindService(Intent service,ServiceConnection conn,int flags)该方法有三个参数,三个参数都比较重要,下面依次介绍这三个参数:
• service:通过Intent指定要启动的Service
• conn:ServiceConnection对象用于访问者与Service连接情况,当连接成功则回调该对象的onServiceConneccted(ComponentName name,IBinder service)方法,当访问者与Service由于异常情况终止(unBindService断开连接时不回调)连接时会回调该对象的onServiceDisconnected(ComponentName name)方法。
• flags:指定绑定时是否自动创建Service,0为不自动创建,BIND_AUTO_CREATE为自动创建。
我们可以看到Service中的onBind方法会返回一个IBinder对象,于此同时,我们看到bindService中conn参数对应的对象中有个方法onServiceConneccted(ComponentName name,IBinder service),这里面有个参数IBinder service,其实这两个IBinder对戏那个是同一个,而组件与Service的通信也是通过IBinder方式来完成的。通常我们采用继承Binder的方式来实现自己的IBinder对象。
下面我们还是通过例子来看一下bindService方式怎么使用:
首先定义了一个Service组件,我们想要看看组件与Service之间的通信情况,所以我们先定义一个接口,方便数据访问:
public interface IBook { //获取书的名字 String getNameById( int Id);}
来看一下我们的Service,这里要重点看我们自己定义的Binder对象,通信就靠它了:
public class ServiceWithBind extends Service { private static String[] bookArr = { "Java", "设计模式" , "IOS开发" , "网络编程" }; // Service被创建时回调此方法 @Override public void onCreate() { super.onCreate(); System. out.println("Service onCreate" ); } // 绑定Service时回调该方法 @Override public IBinder onBind(Intent intent) { System. out.println("Service onBind" ); return new BookBinder(); } // Service被断开连接时回调此方法 @Override public boolean onUnbind(Intent intent) { System. out.println("Service onUnbind" ); return super .onUnbind(intent); } // Service被关闭之前回调此方法 @Override public void onDestroy() { System. out.println("Service onDestroy" ); super.onDestroy(); } // 自定义的IBinder实现类 private class BookBinder extends Binder implements IBook { @Override public String getNameById(int Id) { // TODO Auto-generated method stub if (Id < 0 || Id >= bookArr.length) { return "" ; } else { return bookArr [Id]; } } }}
同样需要在AndroidMenifist中注册:
<service android:name=".ServiceWithBind" ></service>
我们定义一个布局文件activity_bindservice.xml,放上三个按钮,1个绑定按钮,1个解绑定按钮,1个查看通信的按钮:
<?xml version= "1.0" encoding ="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width= "match_parent" android:layout_height= "match_parent" android:background= "#fff" android:gravity= "center" android:orientation= "vertical" > <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:onClick="onBtnBindService" android:text="使用bindService启动" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:onClick="onBtnUnbindService" android:text="使用unbindService停止" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:onClick="onBtnBookName" android:text="查看书的名字" /></LinearLayout>
界面如图所示
在Activity中实现各种方法,注意看通信中重要的ServiceConnection 对象,在哪里可以拿到我们的访问接口:
public class BindDomeActivity extends Activity { private Intent intent; private IBook myBook; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout. activity_bindservice); intent = new Intent(this , ServiceWithBind.class ); } private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub myBook = (IBook) service; } }; //绑定Service的按钮点击事件 public void onBtnBindService(View v) { bindService( intent, conn, Service.BIND_AUTO_CREATE ); } //取消绑定Service的按钮点击事件 public void onBtnUnbindService(View v) { unbindService( conn); } //查看Service中书籍 public void onBtnBookName(View v) { String bookName = myBook.getNameById(2); System. out.println(bookName); Toast. makeText(this, "书名:" + bookName, Toast.LENGTH_SHORT).show(); }}
所有的准备都完成了,下面我们开始测试:
1.进入应用,我们点击启动按钮,这时LogCat输出了两行信息,正如生命周期所示
Service onCreate
Service onBind
2.点击停止按钮,LogCat输出两行信息,说明已经解除连接,并且停止了Service
Service onUnbind
Service onDestroy
3.再重复执行步骤1,这时候Service已经绑定,我们退出应用,会发现有错误提示,这是由于还没有解除绑定就退出组件了,所以会报错,我们开发过程中要注意解除绑定
4.再重复执行步骤1,点击查看书的名字按钮,会提示:书名:IOS开发,这说明我们成功的通信了。
(三)start和bind方式的区别与注意
1、通过startService()和stopService()启动关闭服务。适用于服务和访问者之间没有交互的情况。如果服务和访问者之间需要方法调用或者传递参数,则需要使用bindService()和unbindService()方法启动关闭服务。
2、采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法,这个时候访问者和服务绑定在一起。
3、如果访问者要与服务进行通信,那么,onBind()方法必须返回Ibinder对象。如果访问者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果访问者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()—>onDestroy()方法。
4、Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又 bindService,Service只被创建一次。如果先是bind了,那么start的时候就直接运行Service的onStart方法,如果先是start,那么bind的时候就直接运行onBind方法。如果你先bind上了,就stop不掉了,只能先UnbindService, 再StopService,所以是先start还是先bind行为是有区别的。
0 0
- 4、Service详解(二):本地Service
- Service详解(二)
- Service详解(二):Service生命周期
- <Android> service详解 (二)
- Service组件(本地、远程调用)详解
- Android Service(服务)详解·(二)Service基本用法
- Android中的服务(service)详解(二)--本地服务举例
- Android Service 详解二:创建一个service
- Android Service 详解二:创建一个service
- Android Service 详解二:创建一个service
- Android Service 详解二:创建一个service
- Android Service 详解二:创建一个service
- Android Service 详解二:创建一个service
- Android 四大组件详解(二) Service
- Android中Service服务详解(二)
- Android进阶之(Service详解二)
- Android之Service详解(二)
- Android Service 详解二(超详细)
- Python中函数参数
- unity3d学习之类和方法
- 虚拟机下ubantu的使用心得1
- 文件操作
- hdu 2059 龟兔赛跑 (dp)
- 4、Service详解(二):本地Service
- TypeError: __init__() got an unexpected keyword argument ‘maxlength’
- 多个版本jdk共存环境变量相关说明
- 搜素之任意数的拆分和
- match_parent和fill_parent的区别
- 深搜之全排列
- UML之关系
- C语言scanf函数详细解释
- 最长公共子序列(递归法)