Service知识点全解析(一)

    xiaoxiao2021-03-25  106

    什么是Service?

    Service即服务,是Android四大组件之一,主要用于在后台处理一些计算型的任务。如后台播放音乐等。但是service是在主线程中的,所以耗时任务处理需要在service中开启子线程的。

    Service的特点: 1. 它无法与用户直接进行交互、它必须由用户或者其他程序显式的启动; 2. 它的优先级比较高,它比处于前台的应用优先级低,但是比后台的其他应用优先级高;

    Service的分类: 本地服务:这种服务主要依附于主进程上,因此不需要IPC,也不需要AIDL。在主进程被杀后服务会终止。如音乐软件的播放等。 远程服务:这种服务是在独立的进程上,对应进程名格式为所在包名加上你指定的android:process字符串。如一些提供系统服务的Service,这种Service是常驻的。

    Service 与 Thread 的区别: 请记住这句话:半毛钱关系都没有。一般用service并在其中处理耗时任务,是因为便于控制。

    service的生命周期:

    startService方式启动的服务:onCreate(),onStartCommand,onDestroy()。 bindService方式绑定的服务:onCreate(),onBind(),onUnbind(),onDeatroy()。

    使用service的方式有启动和绑定两种方式。一个service可以既被启动也可以被绑定。若是关闭这种服务,需要调用stopService和unbindService方法解绑并关闭service,与调用的顺序无关。

    注意: 1. 一个已经启动的服务,再次启动只会重复执行onStartCommand方法。 2. 一个已经绑定的服务,再次绑定,生命周期内方法均不会被执行。 3. 停止服务的时候,只需要一次stopService或unbindService即可(若既启动有绑定,需要两个方法都要调用)。

    如何使用service

    清单文件注册(四大组件中除了广播,都需要在AndroidMainfest.xml中注册)

    <application> ... <service android:name=".FirstService"/> ... </application>

    startService方式启动的service类

    public class SecondService extends Service { private static String TAG = "SecondService"; @Nullable @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind"); return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand"); return super.onStartCommand(intent, flags, startId); } }

    bindService方式绑定的service类

    public class FirstService extends Service { private static String TAG = "FirstService"; private MyBinder myBinder = new MyBinder(); @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind"); return myBinder; } @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand"); return super.onStartCommand(intent, flags, startId); } class MyBinder extends Binder { public void downloadTask() { //这里仍是在主线程内,所以若是做耗时操作,需要开启子线程去完成 Log.d(TAG, "downloadTask"); } } @Override public void onDestroy() { Log.d(TAG, "onDestroy"); super.onDestroy(); } }

    activity内调用如下

    public class SecondActivity extends Activity { private static String TAG = "SecondActivity"; @BindView(R.id.startService) Button startService; @BindView(R.id.stopService) Button stopService; @BindView(R.id.bindService) Button bindService; @BindView(R.id.unbindService) Button unbindService; private FirstService.MyBinder myBinder; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); Log.d(TAG, "onCreate"); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Log.d(TAG, "onSaveInstanceState"); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); Log.d(TAG, "onRestoreInstanceState"); } @OnClick({R.id.startService, R.id.stopService, R.id.bindService, R.id.unbindService}) public void onClick(View view) { switch (view.getId()) { case R.id.startService: startService(new Intent(this, FirstService.class)); break; case R.id.stopService: stopService(new Intent(this, FirstService.class)); break; case R.id.bindService: bindService(new Intent(this, FirstService.class), serviceConnection, BIND_AUTO_CREATE); break; case R.id.unbindService: unbindService(serviceConnection); break; } } ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { myBinder = (FirstService.MyBinder) service; myBinder.downloadTask(); } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onDestroy() { super.onDestroy(); stopService(new Intent(this, FirstService.class)); Log.d(TAG, "onDestroy"); } }

    上面已经列出了不同启动的方式和使用方法。如activity内: 一般startService方式启动的service是放任服务执行任务的,交互较少。而bindService方式绑定的service,交互较多。

    bindService方式绑定一个service如下:

    bindService(new Intent(this, FirstService.class), serviceConnection, BIND_AUTO_CREATE);

    这里BIND_AUTO_CREATE表示绑定后自动创建服务。还有很多标志位,查阅源码即知~

    serviceConnection是一个内部类,其中: onServiceConnected方法表示绑定后的回调,onServiceDisconnected是解绑后的回调。

    我们通过onServiceConnected内的向下转型获得binder实例,然后可以调用service内MyBinder的方法downloadTask()。

    myBinder = (FirstService.MyBinder) service; myBinder.downloadTask();

    MyBinder内还有其他的方法通过此实例被activity调用,这也是activity与service通信的一种方式。

    activity与service的通信

    上面的是一种通信方式,是一种被动式通信。若实现service主动向activity通信,还有以下方式~ 1. 接口回调 2. 广播 注意:从不用EventBus,因可读性差,不便维护~

    案例:每秒从service发送进度给activity,并更新在activity的textview上。

    接口回调方式建立通信:

    public interface OnProgressListener { void onProgress(int progress); }

    在service内,接口定义写在MyBinder内了,保持低耦合(一个binder类可以复用在不同的service中哦),其他的是无关代码,省略~

    ... public class MyBinder extends Binder { private OnProgressListener onProgressListener; public void setOnProgressListener(OnProgressListener onProgressListener) { this.onProgressListener = onProgressListener; } public void downloadTask() { //这里仍是在主线程内,所以若是做耗时操作,需要开启子线程去完成 Log.d(TAG, "downloadTask"); new Thread(new Runnable() { @Override public void run() { while (flag && count < 20) { try { Thread.sleep(1000); count++; onProgressListener.onProgress(count); Log.d(TAG, "onStartCommand=" + count); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } } ...

    activity内接受数据更新在Textview上:

    ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { myBinder = (FirstService.MyBinder) service; myBinder.downloadTask(); myBinder.setOnProgressListener(new OnProgressListener() { @Override public void onProgress(final int progress) { Log.d(TAG,"onProgress="+progress); runOnUiThread(new Runnable() { @Override public void run() { showProgress.setText("onProgress="+progress); } }); } }); } @Override public void onServiceDisconnected(ComponentName name) { } };

    runOnUiThread底层也是通过handler异步通信机制的,此类知识点可看

    http://blog.csdn.net/abcjinzi/article/details/53433320

    广播方式建立通信: 很简单的,会用广播就会了,省略了吧~

    个人分述:一般情况下,在同一时刻,服务是一对一与activity交互的,使用接口回调方式通信更方便,广播适合同时刻一对多的情况,而其他情况下都有种“大材小用”的感觉~

    接下来还有对service的进一步研究,敬请期待~

    源码下载

    转载请注明原文地址: https://ju.6miu.com/read-17282.html

    最新回复(0)