文章目录
使用Handler更新UI
- 主线程创建
Handler
对象,重写handlerMessage
方法 - 子线程创建
Message
对象,使用Handler
对象调用sendMessage
方法发送消息,发到MessageQueue
Looper
一直尝试从MessageQueue
中取出待处理消息,分发给Handler的handlerMessage
方法中
java
public class MainActivity extends AppCompatActivity {
// 创建一个 Handler 实例,用于在主线程处理消息
private Handler handler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
// 当接收到的消息的 what 属性为 1 时执行以下代码
if (msg.what == 1) {
// 获取消息中的数据并转换为字符串
String data = (String) msg.obj;
// 将 TextView 的文本设置为接收到的数据
tv.setText(data);
}
}
};
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置活动的布局
setContentView(R.layout.activity_main);
// 获取布局文件中的 TextView 控件
tv = findViewById(R.id.tv_response);
// 获取布局文件中的 Button 控件
Button button = findViewById(R.id.btn_send);
// 为按钮设置点击事件监听器
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 创建一个新的 Message 对象
Message message = new Message();
// 设置消息的内容
message.obj = "数据";
// 设置消息的标识符
message.what = 1;
// 通过 handler 发送消息
handler.sendMessage(message);
}
});
}
}
Service
基本特点
- 后台执行 :
Service
主要用于在后台执行一些长时间运行的操作,比如音乐播放、文件下载等,而不会影响用户界面的交互。 - 没有界面 :
Service
不像Activity
那样有界面。它运行在后台,通常没有用户界面。 - 主线程 :
Service
运行在主线程中,因此在Service
中执行耗时操作(如网络请求或文件操作)会阻塞主线程,可能会导致应用无响应。为了避免这种情况,通常需要使用异步机制,如AsyncTask
、Handler
或ExecutorService
等。
启动方式
非绑定式服务
(Started Service
)
- 启动方式 :通过
startService()
方法启动。 - 生命周期 :服务的生命周期与启动它的组件无关。服务一旦启动,即使启动它的组件被销毁,服务仍会继续在后台运行,直到它自己被停止(通过
stopSelf()
或stopService()
)。 - 交互 :启动的服务不能被组件直接调用其方法。如果需要与服务进行交互,需要通过广播、
Messenger
或AIDL
等方式。 - 用途:适用于需要在后台执行长时间操作的情况,例如,下载文件、播放音乐等。
使用步骤
- 定义服务
定义一个继承自 Service
的类,并实现它的生命周期方法。
java
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService", "onCreate()");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyService", "onDestroy()");
}
}
- 在
AndroidManifest.xml
中声明服务
确保在你的 AndroidManifest.xml
文件中注册服务:
xml
<service android:name=".MyBoundService" />
- 启动服务
java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View view) {
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
}
-
关闭服务
-
由启动者(通常是Activity)调用
stopService
方法。 -
服务内部调用
stopSelf
方法。
- 由启动者关闭服务
在Activity中,可以通过调用 stopService
来停止服务:
java
Intent intent = new Intent(this, MyService.class);
stopService(intent);
- 服务内部关闭自己
服务可以在内部调用 stopSelf
方法来停止自己:
java
public class MyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 某些逻辑操作完成后,停止服务
stopSelf();
return START_NOT_STICKY;
}
}
绑定式服务
(Bound Service
)
- 启动方式 :通过
bindService()
方法启动。 - 生命周期 :服务的生命周期与绑定它的组件(如
Activity
)有关。绑定服务的存在时间是基于组件的生命周期,如果所有绑定它的组件都被销毁,服务也会被销毁。 - 交互 :允许组件与服务进行交互,组件可以通过
ServiceConnection
接口获取到服务的引用,从而调用服务中的方法。 - 用途:适用于需要与服务进行长期交互的情况,例如,组件需要获取服务的数据或调用服务中的方法。
步骤
- 定义服务
定义一个继承自 Service
的MyBindService
类,并实现 onBind()
方法以返回一个实现IBinder
接口的类的对象。这个 IBinder
对象将用于与客户端进行通信。我们定义一个MyBinder
类继承自Binder
类,Binder
类实现了IBinder
接口
java
public class MyBindService extends Service {
private static final String TAG = "MyBindService";
// 测试服务的方法
public void testService() {
Log.d(TAG, "服务的测试");
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate executed");
super.onCreate();
// 在服务创建时初始化一些资源
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand executed");
// 这里可以处理服务启动时的逻辑
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy executed");
super.onDestroy();
// 在服务销毁时释放资源
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind executed");
return new MyBinder(this);
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind executed");
return super.onUnbind(intent);
// 可以在这里处理服务解绑时的逻辑
}
// Binder类实现了IBinder接口
public class MyBinder extends Binder {
private final MyBindService mMyBindService;
// 构造函数,用于初始化服务实例
public MyBinder(MyBindService myBindService) {
mMyBindService = myBindService;
}
// 提供一个方法来获取服务实例
public MyBindService getService() {
return mMyBindService;
}
// 测试Binder的方法
public void test() {
Log.d(TAG, "MyBinder测试");
mMyBindService.testService();
}
}
}
- 在
AndroidManifest.xml
中声明服务
xml
<service android:name=".MyBoundService" />
- 绑定服务
在你的组件(如 Activity
)中,通过 bindService()
方法绑定到服务。你需要实现 ServiceConnection
接口来处理与服务的连接状态。
java
public class MainActivity extends AppCompatActivity {
// 定义一个MyBinder对象,用于绑定服务后与服务交互
public MyBindService.MyBinder myBinder = null;
// 定义一个ServiceConnection对象,用于管理服务的连接和断开
private ServiceConnection coon = new ServiceConnection() {
// 当服务成功连接时回调该方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 将传入的IBinder对象转换为MyBinder
myBinder = (MyBindService.MyBinder) service;
// 调用MyBinder的test方法,测试服务功能
myBinder.test();
}
// 当服务断开连接时回调该方法
@Override
public void onServiceDisconnected(ComponentName name) {
// 可以在这里处理服务断开时的逻辑
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// 绑定服务的方法
public void bindService(View view) {
Intent intent = new Intent(this, MyBindService.class);
bindService(intent, coon, BIND_AUTO_CREATE);
}
}
- 解除绑定
通过 unbindService()
方法来完成解除绑定的操作
java
@Override
protected void onStop() {
super.onStop();
if (isBound) {
unbindService(connection);
isBound = false;
}
}
服务的绑定和解除绑定的注意事项
- 绑定后:一旦绑定成功,组件可以通过服务提供的方法进行交互。
- 解除绑定后 :如果没有其他组件绑定该服务,服务会被销毁(如果服务是绑定服务),并调用
onDestroy()
方法进行清理。 - 线程处理:如果服务需要执行长时间运行的任务,最好在服务中使用后台线程或异步任务来避免阻塞主线程。
生命周期
Service
的生命周期主要包括以下几个阶段:
onCreate()
: 当服务第一次被创建时调用。通常在这里进行服务初始化。onStartCommand(Intent intent, int flags, int startId)
: 当服务被startService()
方法启动时调用。在这个方法中可以处理服务的任务。返回的int
值决定了服务被系统杀掉后如何重启。onBind(Intent intent)
: 当bindService()
方法被调用时触发。用于提供与Service
的绑定接口。若Service
不需要绑定,可以返回null
。onDestroy()
: 当服务被销毁时调用。通常在这里进行清理工作。
非绑定式
启动阶段
onCreate()
- 只会在服务首次创建时调用一次。适合在这里做一些一次性的初始化工作。
onStartCommand(Intent intent, int flags, int startId)
- 每次调用
startService
时都会执行。可以在这里处理传入的 Intent。
- 每次调用
结束阶段
启动者(Activity)调用 stopService
或服务内部调用 stopSelf
-
当 Activity 调用
stopService(Intent intent)
或服务内部调用stopSelf()
方法时,服务会停止并触发onDestroy
方法。 -
onDestroy()
-
服务销毁前的最后一个方法。适合在这里做一些资源释放的收尾工作。
java@Override public void onDestroy() { super.onDestroy(); // 释放资源 }
-
绑定式
启动阶段
**启动者(Activity)**调用 bindService(Intent intent, ServiceConnection conn, int flags)
onCreate()
- 只会在服务首次创建时调用一次。适合在这里做一些一次性的初始化工作。
onBind(Intent intent)
- 只会在首次绑定时执行一次。返回一个 IBinder 对象,供客户端与服务进行通信。
结束阶段
启动者(Activity)销毁或调用 unbindService
方法
-
当 Activity 销毁或调用
unbindService(ServiceConnection conn)
方法时,会解除与服务的绑定。当没有绑定者时,服务会销毁。 -
onUnbind(Intent intent)
- 解除绑定:当所有客户端都解除绑定时,会调用此方法。可以在这里处理一些解绑相关的逻辑。
-
onDestroy()
- 销毁:服务销毁前的最后一个方法。适合在这里做一些资源释放的收尾工作。
注意事项:
- 服务绑定和解除绑定 :确保在
Activity
的生命周期中正确绑定和解除绑定服务,以避免内存泄漏。 - 资源释放 :在
onDestroy
中释放所有资源,确保服务完全终止时不留下任何资源占用。
++onCreate->onBind->onUnbind->onDestory++
前台Service
前台服务 (Foreground Service) 是一种能够持续运行并与用户进行交互的服务。相比于后台服务,前台服务具有更高的优先级,通常不会被系统回收。
使用步骤
- 创建通知 (Notification)
前台服务必须显示一个通知来告知用户该服务正在运行。可以使用 NotificationCompat.Builder
来创建通知。
java
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("服务正在运行")
.setContentText("前台服务示例")
.setSmallIcon(R.drawable.ic_service_icon)
.build();
- 调用
startForeground
方法
在服务的 onCreate
或 onStartCommand
方法中调用 startForeground(notificationId, notification)
方法,将服务提升到前台状态。
java
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("服务正在运行")
.setContentText("前台服务示例")
.setSmallIcon(R.drawable.ic_service_icon)
.build();
startForeground(1, notification);
// 其他业务逻辑
return START_STICKY;
}
- 申请权限
xml
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
结束
- 完全停止Service :
stopService
或stopSelf
。- 降级Service状态 :
stopForeground(true)
将Service从前台状态退出并移除通知,但Service仍然在运行,只是优先级降低。
结束Service本身
- 正常的结束Service方式 :外部调用
stopService
方法或自身调用stopSelf
方法。这两种方式都会完全停止Service。当Service结束后,所有与之相关的通知也会被移除。
示例:
java
// 通过外部调用
stopService(new Intent(context, MyService.class));
// 通过Service自身调用
stopSelf();
降级为普通Service
退出Service的前台状态,降级为普通Service
- 调用
stopForeground(true)
方法 :这会将Service从前台状态退出,变成普通的后台Service。这样做会降低Service的优先级,在系统内存不足时可能会被回收销毁。参数true
表示同时移除通知。
示例:
java
// 将Service退出前台状态,同时移除通知
stopForeground(true);
elf` 方法。这两种方式都会完全停止Service。当Service结束后,所有与之相关的通知也会被移除。
示例:
java
// 通过外部调用
stopService(new Intent(context, MyService.class));
// 通过Service自身调用
stopSelf();
降级为普通Service
退出Service的前台状态,降级为普通Service
- 调用
stopForeground(true)
方法 :这会将Service从前台状态退出,变成普通的后台Service。这样做会降低Service的优先级,在系统内存不足时可能会被回收销毁。参数true
表示同时移除通知。
示例:
java
// 将Service退出前台状态,同时移除通知
stopForeground(true);
感谢您的阅读
如有错误烦请指正