Service 生命周期变化
1、Service
- BindAndUnbindLifecycleService.java
java
public class BindAndUnbindLifecycleService extends Service {
public static final String TAG = BindAndUnbindLifecycleService.class.getSimpleName();
private IBinder LocalBinder = new BindAndUnbindLifecycleService.BindAndUnbindLifecycleServiceBinder();
public class BindAndUnbindLifecycleServiceBinder extends Binder {
public BindAndUnbindLifecycleService getService() {
return BindAndUnbindLifecycleService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return LocalBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy");
}
}
- AndroidManifest.xml
xml
<service android:name=".myservice.BindAndUnbindLifecycleService" />
2、Activity Layout
- activity_bind_and_unbind_service_test1.xml
xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BindAndUnbindServiceTest1Activity">
<Button
android:id="@+id/btn_bind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绑定服务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_unbind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解绑服务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_bind" />
<Button
android:id="@+id/btn_go"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跳转"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- activity_bind_and_unbind_service_test2.xml
xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BindAndUnbindServiceTest2Activity">
<Button
android:id="@+id/btn_bind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绑定服务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_unbind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解绑服务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_bind" />
<Button
android:id="@+id/btn_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="回退"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
3、Activity Code
- BindAndUnbindServiceTest1Activity.java
java
public class BindAndUnbindServiceTest1Activity extends AppCompatActivity {
public static final String TAG = BindAndUnbindServiceTest1Activity.class.getSimpleName();
private Button btnBind;
private Button btnUnbind;
private Button btnGo;
private BindAndUnbindLifecycleService bindAndUnbindLifecycleService;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected");
BindAndUnbindLifecycleService.BindAndUnbindLifecycleServiceBinder bindAndUnbindLifecycleServiceBinder = (BindAndUnbindLifecycleService.BindAndUnbindLifecycleServiceBinder) service;
BindAndUnbindLifecycleService bindAndUnbindLifecycleService = bindAndUnbindLifecycleServiceBinder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_bind_and_unbind_service_test1);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
btnBind = findViewById(R.id.btn_bind);
btnUnbind = findViewById(R.id.btn_unbind);
btnGo = findViewById(R.id.btn_go);
btnBind.setOnClickListener(v -> {
bindService(new Intent(this, BindAndUnbindLifecycleService.class), serviceConnection, Context.BIND_AUTO_CREATE);
});
btnUnbind.setOnClickListener(v -> {
unbindService(serviceConnection);
});
btnGo.setOnClickListener(v -> {
startActivity(new Intent(this, BindAndUnbindServiceTest2Activity.class));
});
}
}
- BindAndUnbindServiceTest2Activity.java
java
public class BindAndUnbindServiceTest2Activity extends AppCompatActivity {
public static final String TAG = BindAndUnbindServiceTest2Activity.class.getSimpleName();
private Button btnBind;
private Button btnUnbind;
private Button btnBack;
private BindAndUnbindLifecycleService bindAndUnbindLifecycleService;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected");
BindAndUnbindLifecycleService.BindAndUnbindLifecycleServiceBinder bindAndUnbindLifecycleServiceBinder = (BindAndUnbindLifecycleService.BindAndUnbindLifecycleServiceBinder) service;
BindAndUnbindLifecycleService bindAndUnbindLifecycleService = bindAndUnbindLifecycleServiceBinder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_bind_and_unbind_service_test2);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
btnBind = findViewById(R.id.btn_bind);
btnUnbind = findViewById(R.id.btn_unbind);
btnBack = findViewById(R.id.btn_back);
btnBind.setOnClickListener(v -> {
bindService(new Intent(this, BindAndUnbindLifecycleService.class), serviceConnection, Context.BIND_AUTO_CREATE);
});
btnUnbind.setOnClickListener(v -> {
unbindService(serviceConnection);
});
btnBack.setOnClickListener(v -> {
finish();
});
}
}
4、Test
-
在 BindAndUnbindServiceTest1Activity 中,点击【绑定服务】按钮,输出结果
onCreate
onBind
onServiceConnected -
在 BindAndUnbindServiceTest1Activity 中,点击【跳转】按钮,跳转到 BindAndUnbindServiceTest2Activity
-
在 BindAndUnbindServiceTest2Activity 中,点击【绑定服务】按钮,输出结果
onServiceConnected
-
在 BindAndUnbindServiceTest2Activity 中,点击【解绑服务】按钮,输出结果
无内容输出
-
在 BindAndUnbindServiceTest2Activity 中,点击【回退】按钮,回退到 BindAndUnbindServiceTest1Activity
-
在 BindAndUnbindServiceTest1Activity 中,点击【解绑服务】按钮,输出结果
onUnbind
onDestroy
Service 与 Activity 双向交互
1、演示
(1)Service
- ServiceCallback.java
java
public interface ServiceCallback {
void onTaskComplete(int result);
}
- CommunicateService.java
java
public class CommunicateService extends Service {
private final IBinder binder = new CommunicateServiceBinder();
private ServiceCallback serviceCallback;
private final Handler handler = new Handler(Looper.getMainLooper());
public class CommunicateServiceBinder extends Binder {
public CommunicateService getService() {
return CommunicateService.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
// 注册回调
public void setCallback(ServiceCallback serviceCallback) {
this.serviceCallback = serviceCallback;
}
public void startLongTask() {
new Thread(() -> {
// 模拟耗时操作
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 发送数据
int result = 100;
if (serviceCallback != null) {
handler.post(() -> serviceCallback.onTaskComplete(result));
}
}).start();
}
}
- AndroidManifest.xml
xml
<service android:name=".myservice.CommunicateService" />
(2)Activity
- activity_communicate_service_test.xml
xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CommunicateServiceTestActivity">
<TextView
android:id="@+id/tv_test_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="无"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_execute_task"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="执行任务"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- CommunicateServiceTestActivity.java
java
public class CommunicateServiceTestActivity extends AppCompatActivity {
public static final String TAG = CommunicateServiceTestActivity.class.getSimpleName();
private TextView tvTestContent;
private CommunicateService communicateService;
private boolean isBound = false;
private final ServiceCallback serviceCallback = result -> {
tvTestContent.setText(String.valueOf(result));
};
private final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected");
communicateService = ((CommunicateService.CommunicateServiceBinder) service).getService();
isBound = true;
communicateService.setCallback(serviceCallback);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected");
isBound = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_communicate_service_test);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
tvTestContent = findViewById(R.id.tv_test_content);
findViewById(R.id.btn_execute_task).setOnClickListener(v -> {
if (communicateService != null) {
communicateService.startLongTask();
}
});
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, CommunicateService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (isBound) {
if (communicateService != null) {
communicateService.setCallback(null);
}
unbindService(serviceConnection);
isBound = false;
}
}
}
2、小结
| 方向 | 方式 | 关键代码 |
|---|---|---|
| Activity → Service | 直接调用 Service 方法 | communicateService.startLongTask() |
| Service → Activity | 通过回调接口 | serviceCallback.onTaskComplete(result) |