“点滴芭蕉心欲碎,声声催忆当初。欲眠还展旧时书。鸳鸯小字,犹记手生疏。


   倦眼乍低缃帙乱,重看一半模糊。幽窗冷雨一灯孤。料应情尽,还道有情无?”


--------临江仙·点滴芭蕉心欲碎


    对于Android开发中常用的知识四大组件之一Service是一个非常重要的知识点,在之前面试的时候遇到了一系列问题,都是不注重细节(基础知识),若要向上走我们必须了解乃至加深对于基础知识点的理解。下面我将进行service的开发中用到的知识点进行总结。


一、 service的适用场景:


  1. 用于长期执行某些操作,并且甚至与UI(主)线程没有交互。比如启动app直接去网络下载文件
  2. 跨进程间通信,比如appA程序中Service被appB中程序调用

注意: Service默认时运行在它所在的宿主进程的主进程中,也就是说如果我们在Service中做耗时工作,UI(主)线程会卡死,出现ARN程序无响应现象。为了防止这种情况出现,我们一般都是在Service中创建一个新的线程来处理一些耗时工作,这样就不会阻塞主线程。从这里也侧面反映了Service不是另一个独立的进程,Service自己本身不会开辟新的进程,除非手动来设置。默认情况下,Service是运行在本运用程序所属的进程中。



二、生命周期


android 在service里调用按钮的点击事件 android的service使用场合_启动服务


三、Service的两种类型


  1. Started
  • 如果一个应用程序组件(比如一个activity)通过调用startService()来启动服务,则该服务就是被“started”了。一旦被启动,服务就能在后台一直运行下去,即使启动它的组件已经被销毁了。 通常,started的服务执行单一的操作并且不会向调用者返回结果。比如,它可以通过网络下载或上传文件。当操作完成后,服务应该自行终止。
  1. Bound
  • 如果一个应用程序组件通过调用bindService()绑定到服务上,则该服务就是被“bound”了。bound服务提供了一个客户端/服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至可以利用进程间通信(IPC)跨进程执行这些操作。绑定服务的生存期和被绑定的应用程序组件一致。 多个组件可以同时与一个服务绑定,不过所有的组件解除绑定后,服务也就会被销毁。


四、Service注册方式(manifest.xml)


代码如下

<service
        android:name=".service.MyService"
        android:enabled="true"
        android:exported="false">
</service>

官方建议:


  • - 为了确保应用的安全性,请始终使用显式 Intent 启动或绑定 Service,且不要为服务声明 Intent 过滤器。
  • - 添加 android:exported 属性并将其设置为 "false",确保服务仅适用于您的应用。这可以有效阻止其他应用启动您的服务,即使服务提供了intent过滤器,本属性依然生效。




二、Service的两种启动方式


  1. StartService()
  1.  使用startService启动service:
            第一次启动service会调用onCreate,onStartCommand,而后面再次startService则不会再调用onCreate而是onStartCommand,并且每次startId不同.
                stopService
                   调用stopService,情况如下:
    - 如果service已经通过startService启动,则onDestroy
    - 如果service没启动,则没什么效果
  2. 代码如下:
/**启动服务的事件监听*/
    public Button.OnClickListener startService = new Button.OnClickListener(){
        public void onClick(View view){
            /**单击按钮时启动服务*/
            Intent intent = new Intent(MainActivity.this,CountService.class);
            startService(intent);        
        }
    };
  1. 在创建一个自己的service继承Service代码如下:
public class CountService extends Service{
	/**创建参数*/
	boolean threadDisable ;
	int count;
	public IBinder onBind(Intent intent){
		return null;
	}
	public void onCreate(){//创建服务
		super.onCreate();
		/**创建一个线程,每秒计数器加一,并在控制台进行Log输出*/
		new Thread(new Runnable(){
			public void run(){
				while(!threadDisable){
					try{
						Thread.sleep(1000);
					}catch(InterruptedException e){

					}
					count++;
					Log.v("CountService","Count is"+count);
				}
			}
		}).start();
	}
	public void onDestroy(){//销毁
		super.onDestroy();
		/**服务停止时,终止计数进程*/
		this.threadDisable = true;
	}
	public int getConunt(){
		return count;
	}
	class ServiceBinder extends Binder{
		public CountService getService(){
			return CountService.this;
		}
	}
}
  1. 注意:这种方式创建的service停止服务的方法是onDestroy()方法
  1. bindService()
  1.  bindService的参数BIND_AUTO_CREATE表示在Activity和Service建立关联后自动创建Service,这会使得MyService中的onCreate()方法          得到执行,但onStartCommand()方法不会执行。
  2. 不同于startService,bind调用后,设置-正在运行里是看不到有Service运行着的.
  3. 如果没用bindService启动过service(注意:即使是startService启动的也不行),直接调用unbindService,则会崩溃:
                   java.lang.IllegalArgumentException: Service not registered: yifeiyuan.practice.practicedemos.service.ServiceActivity$1@535f696c
  4. 如果不调用onUnbind,直接关掉Activity,跟unBind效果一样,也就是说两者生命周期相同,共存亡.
  5. 多个启动服务的请求将会引发服务onStartCommand()方法的多次调用。不过,只有一个终止服务的请求(用stopSelf()或stopService())会被接受并执行。

五、Service类关系

  1. Service:
  •  这是所有服务的基类。如果你要扩展该类,则很重要的一点是:请在其中创建一个新的线程来完成所有的服务工作。 因为服务默认是使用应用程序的主线程的,这会降低应用程序中activity的运行性能。
  1. IntentService:
  • 这是Service类的子类,它使用了工作(worker)线程来处理所有的启动请求,每次请求都会启动一个线程。 如果服务不需要同时处理多个请求的话,这是最佳的选择。 所有你要做的工作就是实现onHandleIntent()即可,它会接收每个启动请求的intent,然后就可在后台完成工作。
  1. 两者的区别:
  • service:
  • Service不是一个单独的进程 ,它和应用程序在同一个进程中
  • Service不是一个线程,所以我们应该避免在Service里面进行耗时的操作
  • intentService:
  • 会创建独立的worker线程来处理所有的Intent请求;
  • 会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;
  • 所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service;

将知识点总结就在此结束,下一节我会详细介绍service的两种启动方式的代码示例。