Activity调用Service里的方法
2015-03-12 16:58
363 查看
Service是不能被实例化的,那么我们如果想调用里边的方法,该怎样进行呢?
首先看一个Serviece类
我们启动Service,除了StartService之外,还可以通过bindService的方法,得到代理人对象。
首先看Service类的写法有什么不一样
但是在实际的开发中,我们不可能这么直接去写,把代理人写在Service里,那肯定是不行的,而且不能直接定义成public让外部去访问,我们通常是建立一个接口,通过暴露接口的方式来实现。
在Service中,把MyBinder类去实现这个接口
在Activity中做如下修改:
如果我们没有绑定服务,那么Activity退出了,服务还在,但是如果绑定了,那么Activity退出,服务跟着也马上退出。
服务的混合开启:
需求:既要想保证服务长期在后台运行,又想去调用服务里的方法,怎么办呢?
技巧:1、先开启服务——这样就可以保证服务长期运行(不绑定) 2、绑定服务——这样就可以调用里边的方法了
服务只会被创建一次,也就是当我们如果先开启了服务,会执行OnCreate方法,当再绑定服务的时候,onCreate方法不会再执行,直接执行onBind方法。
注意事项:
当我们绑定服务了之后,如果直接退出,会报出异常的错误,为什么呢?因为我们绑定了服务,直接退出会显示异常,怎样解决呢?也就是在我们退出的时候,要把绑定的服务解除掉。
定义一个方法:
服务一旦被绑定,通过StopService方法是不能停止掉的,只能通过解绑之后,才能停止,服务先解绑,然后直接onDestory了,所以绑定了服务,记得要解绑。如果点击多次绑定服务,只会调用一次onBind方法,但是如果调用多次解绑方法,程序第一次会调用解绑,后边就会报错。
为了防止忘记解绑服务,我们通常在Activity的onDestory中调用解绑服务的方法,这样就能保证应用程序在退出的时候,自动把程序解绑掉,但是如果程序员比较勤奋,之前已经解绑过了,那如果再解绑就会报错,怎么办呢?通常情况下我们可以用try_catch方法包围解绑,这样就比较安全了。
首先看一个Serviece类
public class SingService extends Service{ @Override public IBinder onBind(Intent intent) { // TODO 自动生成的方法存根 return null; } @Override public void onCreate() { // TODO 自动生成的方法存根 super.onCreate(); System.out.print("服务启动,开始唱歌了"); } @Override public void onDestroy() { // TODO 自动生成的方法存根 super.onDestroy(); System.out.print("服务结束,停止唱歌了"); } //自定义的方法 public void ChangeSong(String songName){ Toast.makeText(getApplicationContext(), "切换歌曲", 0).show(); } }Activity的代码部分如下:由于这些方法都是按钮的点击事件,所以传入参数View(例如在XML文件中android:click = "start")
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } /* * 开启服务 * */ public void start(View view){ Intent intent = new Intent(this, SingService.class); //采用api创建服务,服务对象是被系统(Android 框架)new 出来的 startService(intent); } /* * 停止服务 * */ public void stop(View view){ Intent intent = new Intent(this, SingService.class); stopService(intent); } /* * 调用服务里的方法,换首歌,由于Service是系统创建的,我们不能NEW对象调用方法 * */ public void change(View view){ //由于系统框架在创建服务的时候,会创建与之对应的上下文,下面的代码是错误的 // SingService service = new SingService(); // service.ChangeSong("月亮之上"); } }那么我们怎样才能调用Service里的方法呢?可以采用代理人模式,不直接调用,而是通过与之有关系的代理人来实现。
我们启动Service,除了StartService之外,还可以通过bindService的方法,得到代理人对象。
首先看Service类的写法有什么不一样
public class SingService extends Service{ @Override <strong>//步骤二:服务在成功绑定的时候会调动onBind方法,返回一个IBinder对象</strong> <span style="font-size:12px;"> </span><span style="font-size:14px;"><span style="color:#ff0000;">public IBinder onBind(Intent intent) { // 当服务被成功绑定的时候,系统自动调用该方法 System.out.print("服务成功被绑定"); //返回自定义的代理人对象,这个很关键 return new MyBinder(); }</span> <span style="color:#ff0000;"> public class MyBinder extends Binder{ //简介的利用代理人,调用了唱歌的方法 <strong>public void CallChangeSong(String name){ ChangeSong(name);</strong> } }</span> </span> @Override public void onCreate() { // TODO 自动生成的方法存根 super.onCreate(); System.out.print("服务启动,开始唱歌了"); } @Override public void onDestroy() { // TODO 自动生成的方法存根 super.onDestroy(); System.out.print("服务结束,停止唱歌了"); } //自定义的方法 public void ChangeSong(String songName){ Toast.makeText(getApplicationContext(), "切换歌曲", 0).show(); } }Activity里的写法:
public class MainActivity extends Activity { <strong>//步骤四:在Activity里面得到服务IBinder对象的引用</strong> private SingService.MyBinder myBinder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void change(View view){ <strong>//步骤五:利用iBinder对象间接的调用了服务里的方法</strong> myBinder.CallChangeSong("月亮之上"); } <strong>//步骤一:采用绑定服务的方式开启服务</strong> public void bind(View view){ Intent intent = new Intent(this, SingService.class); bindService(intent, new MyConn(), BIND_AUTO_CREATE); } //建立一个内部类,代理人 private class MyConn implements ServiceConnection{ //在服务被成功绑定时候调用的方法 @Override public void onServiceConnected(ComponentName name, IBinder service) { System.out.println("把代理人返回来了"); <strong>//第三步:服务返回的IBinder对象会被传递给myConn的回调方法</strong> myBinder = (MyBinder) service; } //在服务失去绑定时候调用的方法,正常情况下不会被调用,只有在进程异常终止时候才会调用。 @Override public void onServiceDisconnected(ComponentName name) { // TODO 自动生成的方法存根 } } }整个的流程如下:
但是在实际的开发中,我们不可能这么直接去写,把代理人写在Service里,那肯定是不行的,而且不能直接定义成public让外部去访问,我们通常是建立一个接口,通过暴露接口的方式来实现。
public interface Iservice { public void callChangeSong(String name); }单独写一个接口,统一规范作用
在Service中,把MyBinder类去实现这个接口
private class MyBinder extends Binder implements Iservice{ @Override public void callChangeSong(String name) { // TODO 自动生成的方法存根 ChangeSong(name); } }
在Activity中做如下修改:
private Iservice myBinder;
myBinder = (Iservice) service;
如果我们没有绑定服务,那么Activity退出了,服务还在,但是如果绑定了,那么Activity退出,服务跟着也马上退出。
服务的混合开启:
需求:既要想保证服务长期在后台运行,又想去调用服务里的方法,怎么办呢?
技巧:1、先开启服务——这样就可以保证服务长期运行(不绑定) 2、绑定服务——这样就可以调用里边的方法了
服务只会被创建一次,也就是当我们如果先开启了服务,会执行OnCreate方法,当再绑定服务的时候,onCreate方法不会再执行,直接执行onBind方法。
注意事项:
当我们绑定服务了之后,如果直接退出,会报出异常的错误,为什么呢?因为我们绑定了服务,直接退出会显示异常,怎样解决呢?也就是在我们退出的时候,要把绑定的服务解除掉。
定义一个方法:
//解除绑定服务的方法 public void unBind(View view){ unbindService(conn); }这时候在Service中会调用onUnbind方法,如下:
public boolean onUnbind(Intent intent) { // TODO 自动生成的方法存根 System.out.println("解除绑定"); return super.onUnbind(intent); }
服务一旦被绑定,通过StopService方法是不能停止掉的,只能通过解绑之后,才能停止,服务先解绑,然后直接onDestory了,所以绑定了服务,记得要解绑。如果点击多次绑定服务,只会调用一次onBind方法,但是如果调用多次解绑方法,程序第一次会调用解绑,后边就会报错。
为了防止忘记解绑服务,我们通常在Activity的onDestory中调用解绑服务的方法,这样就能保证应用程序在退出的时候,自动把程序解绑掉,但是如果程序员比较勤奋,之前已经解绑过了,那如果再解绑就会报错,怎么办呢?通常情况下我们可以用try_catch方法包围解绑,这样就比较安全了。
相关文章推荐
- service调用Activity中的方法
- Android实现Activity、Service与Broadcaster三大组件之间互相调用的方法详解
- 在Activity中调用本地服务(Service)中的方法
- Activity调用Service的方法
- Activity 调用Service的方法
- 如何从Activity中调用Service中的方法
- 在Activity中调用本地服务(Service)中的方法
- 在Activity中调用Service的方法——本地服务
- 在Activity中调用Service的非静态方法
- 在Activity里调用Service中的方法以及MediaPlay类的使用
- activity调用service中方法的几种方案
- Activity与Service绑定(activity调用service方法)--安卓软件开发
- 在Activity中调用本地服务(Service)中的方法
- android java开发 第三天 之 Activity 与 Service 绑定(activiey 调用service中方法)
- Android学习笔记:Activity跨进程调用service。
- Android Service 通知Activity更新界面的方法研究
- activity和service之间的相互通信方法
- Boost asio学习笔记之一—— 使用strand支持多线程调用service_io的方法
- Android Service 通知Activity更新界面的方法研究
- C# webservice调用方法总结