Android面试系列之二

来源:互联网 发布:斗战三国志ol进阶数据 编辑:程序博客网 时间:2024/06/05 02:20

11, 谈谈对service的理解?

Service,服务。幕后工作者,甘心做绿叶。默默为前台提供支持。Android的核心三组件可以通过电视台进行比喻,电视播放画面可以看作Activity,用户可以通过遥控器切换不同的电视台可以看做是不同Activity之间的切换。电视播放的新闻可以看做是广播发送方,每个观众都是接收者。而电视幕后工作者可以看做是Service,从不抛头露面。默默为Activity提供所需要的内容。

 

说到Service,我们最熟悉莫过于windows中的服务。他们都是在后台长时间运行,接受上层指令,完成相关操作。但android中的service与其他的服务还是有所差别的,service与其他三个组件一样,其进程模型都是可以通过XML进行配置的。调用方和发布方都可以有权利来选择是把这个组件运行在同一个进程下,还是不同的进程下。如果一个Service,是有期望运行在于调用方不同进程的时候,就需要利用Android提供的RPC(Remote Procedure Call Protocol)机制,为其部署一套进程间通信的策略。当然这些策略android已经为你封装好了。你需要了解底层。直接拿来使用即可。RPC其实就是代理模式的一种实现,在调用端和服务端都去生成一个代理类,做一些序列化和反序列化的事情,使得调用端和服务器端都可以像调用一个本地接口一样使用RPC接口。

 

Android中用来做数据序列化的类是Parcel,封装了序列化的细节,向外提供了足够对象化的访问接口

 

AIDL (Android Interface Definition Language) ,一种接口定义的语言,服务的RPC接口,可以用AIDL来描述, ADT帮助你自动生成一整套的代理模式需要用到的类,不要要你自己写。下面会给个例子。

12, service的生命周期?

在有生命周期的这几个组件中,Service的生命周期最长,其次是Activity最后Receiver。

Service的生命周期相对Activity简单一些。Service提供了两种启动service的方式,每一种方式对应一套生命周期方法。以下是android提供的图片:

  

 
1)  以startService()方式启动的服务,它的生命周期如下:

onCreate()->onStartCommand()这时服务已经开启,如果再点击一下启动则只会调用onStartCommand()。这说明service是单例的,只实例化一次。点击停止按钮调用onDestroy()。销毁。生命周期完成。以下为图示:



 
  
2)  以bindService()方式启动服务。调用方式如下:

onCreate()->onBind() 此时服务绑定。再次绑定则无响应。解除绑定:onUnbind()->onDestroy()。生命周期完成。如图所示:



 


 

  13, 启动service的两种方法?有什么区别?

一种是startService(),另一种是bindService()。这两者的区别是第一种方式调用者开启了服务,即会与服务失去联系,两者没有关联。即使访问者退出了,服务仍在运行。如需解除服务必须显式的调用stopService方法。主要用于调用者与服务没有交互的情况下,也就是调用者不需要获取服务里的业务方法。比如电话录音。而后者调用者与服务绑定在一起的。当调用者退出的时候,服务也随之退出。用于需要与服务交互。

 

14, 实现进程内与进程间通信是怎么实现的?

在linux中进程通信机制有很多种,比如:消息队列(message queue),socket,共享内存(share mermory)等等。但是在Android中,无论是进程内还是进程间,所采用的通信机制,主要是以Binder为核心。Android之所以选择是Binder作为进程的通信机制,主要是Binder与其他通信方式相比更加快速和简洁,所消耗的内存也是相对较少。当然也有其他方面的原因,比如传统进程通信有可能会增加进程开销,也有安全方面的风险。Binder能解决这些问题。故成为首选的通信方式。

1)  进程内的通信,与进程间的通信相比,相对容易些。进程内通信肯定要采用绑定的方式开启服务。这样才能与服务进行交互。绑定服务的方法:

bindService(Intent service, ServiceConnection conn, int flags)

这个方法的第一个参数很好理解。用于激活哪个服务,第二个参数是关键,服务的连接,这是一个接口,用于接收服务开启或者关闭时返回的数据。实现这个接口要重写两个方法:

onServiceConnected(ComponentName name, IBinder service):一旦客户端与服务端绑定成功,将有这个方法的第二个参数接收服务端返回的IBinder对象。得到服务端的引用就可以在客户端调用服务里的一些业务方法。这也是进程内通信的主要部分。

onServiceDisconnected(ComponentName name):这个方法在服务断开是调用,服务被销毁或者被干掉时调用。附件处有例子。

2)  进程之间的通信,其主要的核心机制同样是Binder。其实Binder底层就是通过Parcel(邮包)来完成数据传输的。进程内通信可以通过IBinder对象来实现业务共享的,但是进程间的通信这种方式就肯定不行了。这时就用到了AIDL。

 

AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码,实现Android设备上的两个进程间通信(IPC).AIDL的IPC机制和EJB所采用的CORBA很类似,进程之间的通信信息,首先会被转换成AIDL协议消息,然后发送给对方,对方收到AIDL协议消息后再转换成相应的对象.由于进程之间的通信信息需要双向转换,所以android采用代理类在背后实现了信息的双向转换,代理类由android编译器生成,对开发人员来说是透明的.

 

使用方式如下:

定义AIDL. //XXXService.aidl,注意扩展名

package com.iteye.androidtoast;

interface XXXService {

  void sayHello(in/out/inout String name);//in|out|inout是参数的方向

}

ide会自动在gen包下生成对应的java类,接口文件中生成一个Stub的抽象类,里面包括aidl定义的方法,还包括一些其它辅助方法.值得关注的是asInterface(IBinder iBinder),它返回接口类型的实例,对于远程服务调用,远程服务返回给客户端的对象为代理对象,客户端onServiceConnected(ComponentName name, IBinder service)方法引用该对象时不能直接强转成接口类型的实例,而应该使用asInterface(IBinder iBinder)进行类型转换.

AIDL定义注意事项:

(1)接口名和aidl文件名相同.

(2)接口和方法前不用加访问权限修饰符public,private,protected等,也不能用final,static.

(3)AIDL默认支持的类型包话java基本类型(int,long,boolean等)和(String,List,Map,

  CharSequence),使用这些类型时不需要import声明.对于List和Map中的元素类型必须是AIDL支持的类型.如果使用自定义类型作为参数或返回值,自定义类型必须实现Parcelable接口.

  (4)自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中.

  (5)在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数.

  (6)Java原始类型默认的标记为in,不能为其它标记.

 

 

具体步骤:

1.创建服务器android项目(server)

 

2.创建服务类.CustomerService

              /**

               * 服务类

               */

              public class CustomerService extends Service {

                     ...

              }

 3.配置清单注册服务类

              <!-- 注册服务 -->

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

4.定义aidl文件.

              ICustomerService.aidl

              package com.iteye.androidtoast.aidl;

 

              interface ICustomerService {

                     String sayHello(String name);

              }

 

 5.ide在gen目录下自动生成java接口.

 

 6.需要实现CustomerService.onBind()方法的返回值.

              public IBinder onBind(Intent intent) {

                     return new ICustomerService.Stub() {

                            public String sayHello(String name) throws RemoteException {

                                   return "hello " + name;

                            }

                     };

              }

   7.创建客户端项目(android项目)

 

   8.复制服务端项目aidl文件到客户端(连同包结构一同复制),同样在客户端项目中

         也会生成对应的接口类.同步骤(5).

 

   9.绑定服务.

              class CustomerConnection implements ServiceConnection{

                     public void onServiceConnected(ComponentName name, IBinder service) {

                            is = ICustomerService.Stub.asInterface(service);

                     }

                     public void onServiceDisconnected(ComponentName name) {

                     }

              }

   10.绑定服务

              Intent i = new Intent();

              i.setAction(“”)

              this.bindService(i, conn, BIND_AUTO_CREATE);

 

  11,调用远程服务方法


  • service生命周期.rar (45.6 KB)
  • 下载次数: 39
  • 进程间通信.rar (102.8 KB)
  • 下载次数: 43
  • 进程内通信.rar (46.9 KB)
  • 下载次数: 46
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 浙江嵊泗人在金华丢了身份证怎么办 一证5号够了怎么办新卡 微信号被盗实名认证是自己的怎么办 苹果微信登录显示被盗风险怎么办 在诈骗公司上班被公安抓了怎么办 在国外护照不小心撕坏了怎么办 在俄罗斯护照超期拉黑应该怎么办 俄罗斯五年定居护照丢了怎么办 百家号文章质量分一直在下降怎么办 如果在韩国把护照弄丢了怎么办 坐亲戚的车出了车祸受伤怎么办 出了车祸受伤对方不拿医药费怎么办 如果找你买保险的不在了保单怎么办 赴美生子父母一方是绿卡怎么办 农保报销需要居住证过期了怎么办 有上海户口但没有户口本怎么办护照 签证用的旧护照丢失了英签怎么办 买的动迁房房东不肯过户怎么办 身份信息在qq邮箱泄露了怎么办 别人用我的身份证贷款不还怎么办 做兼职被骗了身份证泄露了怎么办 qq绑定的手机号被别人换了怎么办 银行卡丢失不知道卡号和密码怎么办 美团景点门票过了退款期怎么办 我的手机汽车之家无法看视频怎么办 来事泡温泉细菌感染外阴瘙痒怎么办 西澳大学语言班没通过怎么办 银行入职培训理论考试不合格怎么办 去泰国旅游不会泰语和英语的怎么办 老板不发工资怎么办没签合同的 3d模型导进去材质丢失怎么办 七日杀显示载入中之后进不去怎么办 进京证过期了车在北京怎么办 微信打字时剪切的东西丢了怎么办 错过了医师定期考核报名时间怎么办 大学档案在自己手里放多年怎么办 档案在自己手里10年了怎么办 快递地址区域划分写错了怎么办 怀孕八个月肛门长个肉疙瘩怎么办呢 客户签了合同不要货了怎么办 不喂母乳宝宝只认识保姆了怎么办?