1 service是什么
Service是Android系统中的四大组件之一,它是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序。
2 service分类
3 service启动方式
3.1 startService显示启动
// AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyApplication"> <activity android:name=".StartServiceActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".StartService" /> </application> </manifest>
// StartSeviceActivity.java package com.example.myapplication; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; //import com.ttit.helloworld.R; public class StartServiceActivity extends AppCompatActivity { private Button start; private Button stop; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.service_layout); start = (Button) findViewById(R.id.btnstart); stop = (Button) findViewById(R.id.btnstop); final Intent intent = new Intent(StartServiceActivity.this, StartService.class); start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startService(intent); } }); stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopService(intent); } }); } }
// StartService.java package com.example.myapplication; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; import android.os.Bundle; public class StartService extends Service { private final String TAG = "service"; //必须要实现的方法 @Override public IBinder onBind(Intent intent) { Log.e(TAG, "onBind方法被调用!"); return null; } //Service被创建时调用 @Override public void onCreate() { Log.e(TAG, "onCreate方法被调用!"); super.onCreate(); } //Service被启动时调用 @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "onStartCommand方法被调用!"); return super.onStartCommand(intent, flags, startId); } //Service被关闭之前回调 @Override public void onDestroy() { Log.e(TAG, "onDestory方法被调用!"); super.onDestroy(); } }
// service_layout.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btnstart" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="开始服务"/> <Button android:id="@+id/btnstop" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="停止服务"/> </LinearLayout>
1> 通过按钮"开始服务"启动service
final Intent intent = new Intent(StartServiceActivity.this, StartService.class); start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startService(intent); } });
2> 创建StartService 继承service类
public class StartService extends Service
在StartService中实现 onBind,onCreate,onStartCommand, onDestroy方法
3> 在AndroidManifest.xml 清单文件中注册
<service android:name=".StartService" />
4> 运行结果
点击开始服务,运行结果如下:
多次点击开始服务,运行结果如下:
点击停止服务,运行结果如下:
3.2 bindService绑定启动
//AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyApplication"> <activity android:name=".BindServiceActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".BindService" /> </application> </manifest>
// BindServiceActivity.java package com.example.myapplication; import android.app.Service; 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.Toast; import androidx.appcompat.app.AppCompatActivity; public class BindServiceActivity extends AppCompatActivity { private Button btnbind; private Button btncancel; private Button btnstatus; //保持所启动的Service的IBinder对象,同时定义一个ServiceConnection对象 private BindService.MyBinder binder; private ServiceConnection conn = new ServiceConnection() { //Activity与Service断开连接时回调该方法 @Override public void onServiceDisconnected(ComponentName name) { Log.e("service", " ------Service DisConnected-------"); } //Activity与Service连接成功时回调该方法 @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.e("service", " ------Service Connected------ - "); binder = (BindService.MyBinder) service; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.bind_service_layout); btnbind = (Button) findViewById(R.id.btnbind); btncancel = (Button) findViewById(R.id.btncancel); btnstatus = (Button) findViewById(R.id.btnstatus); final Intent intent = new Intent(BindServiceActivity.this, BindService.class); btnbind.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //绑定service bindService(intent, conn, Service.BIND_AUTO_CREATE); } }); btncancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //解除service绑定 unbindService(conn); } }); btnstatus.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getApplicationContext(), "Service的count的值为:" + binder.getCount(), Toast.LENGTH_SHORT).show(); } }); } @Override protected void onDestroy() { super.onDestroy(); unbindService(conn); // 销毁Activity时需要解绑Service } }
// BindService package com.example.myapplication; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class BindService extends Service { private final String TAG = "service"; private int count; private boolean quit; //定义onBinder方法所返回的对象 private MyBinder binder = new MyBinder(); public class MyBinder extends Binder { public int getCount() { return count; } } //必须实现的方法,绑定改Service时回调该方法 @Override public IBinder onBind(Intent intent) { Log.e(TAG, "onBind方法被调用!"); return binder; } //Service被创建时回调 @Override public void onCreate() { super.onCreate(); Log.e(TAG, "onCreate方法被调用!"); //创建一个线程动态地修改count的值 new Thread() { public void run() { while (!quit) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count++; Log.e(TAG, "count = " + count); } } }.start(); } //Service断开连接时回调 @Override public boolean onUnbind(Intent intent) { Log.e(TAG, "onUnbind方法被调用!"); return true; } //Service被关闭前回调 @Override public void onDestroy() { super.onDestroy(); this.quit = true; Log.e(TAG, "onDestroyed方法被调用!"); } @Override public void onRebind(Intent intent) { Log.e(TAG, "onRebind方法被调用!"); super.onRebind(intent); } }
layout截图如下:
运行结果如下:
点击绑定SERVICE:
4 service生命周期
startService启动的生命周期
onCreate() 当Service第一次被创建时,由系统调用。
onStartCommand() 当startService方法启动Service时,该方法被调用。
onDestroy() 当Service不再使用时,由系统调用。
注意:一个startService只会创建一次,销毁一次,但可以开始多次,因此,onCreate()和onDestroy()方法只会被调用一次,而onStartCommand()方法会被调用多次。
bindService启动的生命周期
onCreate() 当Service被创建时,由系统调用。
onBind() 当bindService方法启动Service时,该方法被调用。
onUnbind() 当unbindService方法解除绑定时,该方法被调用。
onDestroy() 当Service不再使用时,由系统调用。
注意:一个bindService可以创建多次,销毁多次,重复使用。
5 service和thread的区别
结论:Service和Thread之间没有任何关系
之所以有不少人会把它们联系起来,主要因为Service的后台概念
后台的定义:后台任务运行完全不依赖UI,即使Activity被销毁,或者程序被关闭,只要进程还在,后台任务就可以继续运行
其实二者存在较大的区别,如下图:
一般来说,会将Service和Thread联合着用,即在Service中再创建一个子线程(工作线程)去处理耗时操作逻辑,如下代码:
@Override public int onStartCommand(Intent intent, int flags, int startId) { //新建工作线程 new Thread(new Runnable() { @Override public void run() { // 开始执行后台任务 } }).start(); return super.onStartCommand(intent, flags, startId); } class MyBinder extends Binder { public void service_connect_Activity() { //新建工作线程 new Thread(new Runnable() { @Override public void run() { // 执行具体的下载任务 } }).start(); } }