Service是Android系统中的四大组件之一,它是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序。
// AndroidManifest.xml
<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
<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> 运行结果
点击开始服务,运行结果如下:
多次点击开始服务,运行结果如下:
点击停止服务,运行结果如下:
//AndroidManifest.xml
<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);
}
}
startService启动的生命周期
onCreate() 当Service第一次被创建时,由系统调用。
onStartCommand() 当startService方法启动Service时,该方法被调用。
onDestroy() 当Service不再使用时,由系统调用。
注意:一个startService只会创建一次,销毁一次,但可以开始多次,因此,onCreate()和onDestroy()方法只会被调用一次,而onStartCommand()方法会被调用多次。
bindService启动的生命周期
onCreate() 当Service被创建时,由系统调用。
onBind() 当bindService方法启动Service时,该方法被调用。
onUnbind() 当unbindService方法解除绑定时,该方法被调用。
onDestroy() 当Service不再使用时,由系统调用。
注意:一个bindService可以创建多次,销毁多次,重复使用。
结论: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();
}
}