赞
踩
目录
2、 IntentService服务为什么可以自动创建线程?为什么可以自动结束服务?
Service是Android的四大组件之一。
作用:
后台长期处理耗时的逻辑。
Service与Activity的区别:
不同点:Service与Activity功能大抵相同,区别在于Service不存在UI界面,Service在后台运行,不能与用户进行交互功能。
相同点:都需要在清单文件中注册,且都有生命周期。
Service的特点:
(1)、在后台运行,即使应用退出,也不会停止服务,只有在杀死APP进程时,才会停止服务。
(2)、Service运行在主线程中。所以,当我们执行一些耗时的操作时,可以在服务中创建子线程来处理耗时的操作。
(3)、Service应用广泛,例如:音乐播放,下载文件等。
更多关于Service的内容详见官方文档:服务概览 | Android 开发者 | Android Developers
对于Service服务我们都不陌生,它大概在我们手机中是这样的。
接下来开始学习如何使用Service服务吧。
按照启动方式可以分为:
当组件通过调用 startService() 方法启动 Service ,这时,Service处于启动状态,可以在后台无限期的运行,只有自身调用stopSelf() 方法 或者 其他组件调用 stopService() 方法才会停止Service。
当组件通过调用 bindService() 方法绑定 Service,这时,Service处于绑定状态,多个组件可以绑定在一个Service上,当绑定Service的所有组件解绑之后,该Service被销毁。
两种启动方式的生命周期如下:
startService():启动服务
(手动调用)不受调用组件的控制,可以在后台无限期的运行。
bindService():绑定服务
(手动调用)将多个组件与服务绑定在一块,随着组件的消亡而消亡。
onCreate():创建服务
(自动调用)无论是开启服务还是绑定服务,最开始的回调函数肯定是onCreate(),当第一次创建Service的时候调用该方法,多次调用startService()方法不会重复调用onCreate() 方法。适合做一些初始化操作。
onStartcommand():重复开始服务
(自动调用)当多次执行startService()方法的时候,onStartcommand()都会执行。
onBind():绑定服务
(自动调用)当一个组件想要通过bindService()
绑定service时,系统会回调该方法。该方法需要实现一个接口,通过返回IBinder对象实现用户通信。若不需要绑定service则返回null,否则必须实现。
unbindService():解绑服务【相对于某个组件来说】
(手动调用)当组件想要与该服务解绑时调用,只有在所有用户解绑之后才会调用onUnbind()回调函数。
onUnbind():解绑服务【相对于服务来说】
(自动调用)当所有捆绑服务的组件解绑之后,系统自动调用onUnbind()函数,将服务解绑。
onDestroy():销毁服务
(自动调用)当Service调用这个函数的时候,这个服务就销毁停止了。下次在用的时候只能执行onCreate()函数进行创建。
stopService():结束服务
(手动调用)其他组件通过调用该函数,将以startService()启动的Service停止掉。
stopSelf():结束服务
(手动调用)当前Service调用此方法来终结自己。
案例:在MainActivity中定义四个按钮,分别是:启动服务,绑定服务,解绑与结束服务。点击相应的按钮完成相应的功能。
activity_main.xml代码
- <?xml version="1.0" encoding="utf-8"?>
- <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"
- tools:context=".MainActivity"
- android:orientation="vertical">
-
- <Button
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="启动服务"
- android:id="@+id/start_button"/>
-
- <Button
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="绑定服务"
- android:id="@+id/bind_button"/>
-
- <Button
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="解除绑定"
- android:id="@+id/unbind_button"/>
-
- <Button
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="结束服务"
- android:id="@+id/stop_button"/>
-
- <TextView
- android:id="@+id/text"
- android:text="XXXXXX"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:textSize="28sp"/>
-
- </LinearLayout>
AndroidManifest.xml
注册服务:<service>
其中有两个属性:
1、android:enabled:表示指定的Service能否被实例化,true表示能,false表示不能。
2、android:exported:表示指定的其他组件能否调用Service或者与其交互,true表示能,false表示不能。当该值为false时,只有同应用的组件或者具有相同用户ID的程序才能启动或者绑定到Service 。
- <!-- 注册服务 -->
- <service android:name=".MyService"/>
MainActivity.java
- package com.example.servicedemo1;
-
- import androidx.appcompat.app.AppCompatActivity;
-
- import android.content.ComponentName;
- import android.content.Intent;
- import android.content.ServiceConnection;
- import android.os.Bundle;
- import android.os.IBinder;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import android.widget.TextView;
- import android.widget.Toast;
-
- public class MainActivity extends AppCompatActivity {
-
- private Button start_button;
- private Button bind_button;
- private Button unbind_button;
- private Button stop_button;
- private TextView text;
-
- private static final String TAG1 = "serviceConnection";
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- //代码重构
- extracted();
-
- //创建Intent对象,用于服务相关操作
- Intent intent = new Intent(MainActivity.this, MyService.class);
- //启动服务
- startListener(intent);
- //绑定服务
- bindORunbindListener(intent);
- //结束服务
- stopListener(intent);
-
- }
-
- /**
- * 代码重构,获取控件
- */
- private void extracted() {
- start_button = this.findViewById(R.id.start_button);
- bind_button = this.findViewById(R.id.bind_button);
- unbind_button = this.findViewById(R.id.unbind_button);
- stop_button = this.findViewById(R.id.stop_button);
- text = this.findViewById(R.id.text);
- }
-
- /**
- * 点击启动服务按钮事件
- * @param intent
- */
- private void startListener(Intent intent) {
- //点击“启动服务”的事件处理
- start_button.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //startService():启动服务
- startService(intent);
- //将结果显示到页面
- text.setText("我已经启动服务啦!");
- }
- });
- }
-
- /**
- * 点击绑定与解绑服务的按钮事件
- *
- * @param intent
- */
- private void bindORunbindListener(Intent intent) {
-
- ServiceConnection serviceConnection = new ServiceConnection() {
-
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- Log.e(TAG1,"调用onServiceConnected");
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- Log.e(TAG1,"调用onServiceDisconnected");
- }
- };
-
- 点击“绑定服务”的事件处理
- bind_button.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //bindService():绑定服务
- bindService(intent,serviceConnection,BIND_AUTO_CREATE);
- text.setText("我已经绑定服务啦!");
- }
- });
-
- 点击“解除绑定”的事件处理
- unbind_button.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //unbindService():解绑服务
- unbindService(serviceConnection);
- text.setText("解除绑定服务啦!");
- }
- });
- }
-
- /**
- * 结束服务按钮事件
- */
- private void stopListener(Intent intent) {
- //点击“结束服务”的事件处理
- stop_button.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //stopService():结束服务
- stopService(intent);
- text.setText("服务已经结束啦!");
- }
- });
- }
-
- }
MyService.java
- package com.example.servicedemo1;
-
- import android.app.Service;
- import android.content.Intent;
- import android.os.IBinder;
- import android.util.Log;
-
- public class MyService extends Service {
-
- private static final String TAG = "MyService";
-
- @Override
- public void onCreate() {
- super.onCreate();
- Log.d(TAG, "创建服务 ——> onCreate()");
- }
-
- @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);
- }
-
- @Override
- public boolean onUnbind(Intent intent) {
- Log.d(TAG, "解绑服务 ——> onUnbind()");
- return super.onUnbind(intent);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- Log.d(TAG, "销毁服务 ——> onDestroy()");
- }
- }
结果:
(1)、第一次点击“启动服务”时:onCreate() ——> onStartCommand()
(2)、再次点击“启动服务”时:onStartCommand()
(3)、点击“启动服务”后又点击“绑定服务”时:onCreate() ——> onBind()
(4)、点击“解绑服务”时:onUnbind()
(5)、点击“结束服务”时:onDestroy()
如图:
由于Service不会专门启动一个线程执行一些耗时的操作,导致所有的操作都是在主线程中进行的,稍不留神就会造成ANR异常,所以需要手动来创建一个线程可供Service执行耗时操作。
另一个原因就是:Service启动后不会停止,只有在自身调用 stopSelf() 方法或者其他组件调用 stopService() 方法时才停止。
而IntentService很好的避免了这两个问题。
首先创建一个Service,让他继承IntentService类,然后在清单文件注册Service。
<service android:name=".MyIntentService"/>
- public class MyIntentService extends IntentService {
- }
然后在MainActivity.java 中启动MyIntentService
- Intent intent1 = new Intent(MainActivity.this, MyIntentService.class);
- startService(intent1);
最后编写MyIntentService代码,使他完成一个耗时操作。
- package com.example.servicedemo1;
- import android.app.IntentService;
- import android.content.Intent;
- import android.util.Log;
- import android.widget.Toast;
-
- import androidx.annotation.Nullable;
-
- /**
- * intentService服务完成一个耗时操作
- */
- public class MyIntentService extends IntentService {
- private static final String TAG = "MyIntentService";
-
- @Override
- public void onCreate() {
- super.onCreate();
- Log.i(TAG, "onCreate");
- }
- //构造方法
- public MyIntentService() {
- super("MyIntentService");
- }
-
- //耗时任务
- @Override
- protected void onHandleIntent(@Nullable Intent intent) {
- int i = 10;
- Log.e(TAG,"IntentService服务启动");
- Toast.makeText(this, "IntentService服务启动", Toast.LENGTH_SHORT).show();
- while (i > 0) {
- Log.i(TAG, i + "");
- i--;
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- Log.e(TAG,"IntentService服务结束");
- Toast.makeText(this, "IntentService服务结束", Toast.LENGTH_SHORT).show();
- }
-
- @Override
- public void onDestroy() {
- Log.i(TAG, "onDestroy");
-
-
- }
- }
效果如下:
当启动IntentService时,会自动开启一个Thread,进行耗时操作,当Thread运行结束之后,IntentService也会结束。
通过源码了解一下他的处理方式。
IntentService是一个抽象类,继承Service类,所以它是一种特殊的Service,因为它内部封装了handlerThread和handler的。
public abstract class IntentService extends Service
下面看onCreate()方法。
- private volatile Looper mServiceLooper;
- private volatile ServiceHandler mServiceHandler;
- private String mName;
-
-
- @Override
- public void onCreate() {
-
- super.onCreate();
- HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
- thread.start();
-
- mServiceLooper = thread.getLooper();
- mServiceHandler = new ServiceHandler(mServiceLooper);
- }
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); 创建了一个Handler线程,thread.start() 启动了这个线程。
thread.getLooper() 获取这个线程的Looper对象。
new ServiceHandler(mServiceLooper) 创建一个内部类ServiceHandler对象,将Looper对象传递给它。
下一步走到了 onStartCommand() 方法
- @Override
- public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
- onStart(intent, startId);
- return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
- }
这个方法里第一件事做的就是,调用onStart() 方法。
接下来看onStart() 方法
- @Override
- public void onStart(@Nullable Intent intent, int startId) {
- Message msg = mServiceHandler.obtainMessage();
- msg.arg1 = startId;
- msg.obj = intent;
- mServiceHandler.sendMessage(msg);
- }
通过 mServiceHandler.sendMessage(msg) 将message发送到消息队列,消息处理又回到serviceHandler里面的handleMessage做。
紧接着回到内部类 ServiceHandler 中 执行 handleMessage() 方法。
- private final class ServiceHandler extends Handler {
- public ServiceHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- onHandleIntent((Intent)msg.obj);
- stopSelf(msg.arg1);
- }
- }
在这个方法中,调用了 onHandleIntent((Intent)msg.obj) 这个抽象方法,但它留给子类去实现。
- @WorkerThread
- protected abstract void onHandleIntent(@Nullable Intent intent);
最后调用 stopSelf(msg.arg1) 停止服务,给出的定义是立即停止,但是当有参数的时候,会等所有的任务都执行完,才停止服务。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。