目录

一、什么是Service

二、启停 Service

三、绑定 Service

四、前台服务

五、远程服务扩展

六、服务保活

七、服务启动方法混用


你可以把Service想象成一个“后台默默打工的工人”。它没有UI界面,默默地在后台干活,比如播放音乐、下载文件、处理网络请求等。即使你退出了App,Service也可以继续运行。

一、什么是Service

Service是Android应用的核心后台组件。

1. 无界面后台任务

  • Service 是 Android 系统中无可视化界面、运行于后台的长生命周期组件。
  • 核心功能:执行与用户界面无关的持续性任务,如后台播放音乐、文件下载等。
  • Service 不依赖用户交互界面,生命周期独立于Activity。
  • 典型应用场景:网络请求、传感器数据采集、跨进程通信(AIDL)。

2. 生命周期管理

Service有两种主要类型:

特性Started Service(启动式)Bound Service(绑定式)
启动方式通过 startService(Intent) 启动通过 bindService(Intent, ServiceConnection, flags) 启动
生命周期onCreate() → onStartCommand() → onDestroy()onCreate() → onBind() → onUnbind() → onDestroy()
通信机制无法直接与组件交互,需通过广播或 Intent 传递数据通过 Binder 接口直接通信(支持方法调用)
销毁条件需手动调用 stopSelf() 或 stopService()所有绑定组件解绑后自动销毁
多组件绑定不支持,每次启动独立运行支持多个组件同时绑定(如多个 Activity 共享同一服务实例)
适用场景一次性后台任务(如下载、音乐播放)长期交互服务(如数据同步、实时计算)
优先级与系统回收后台服务可能被系统回收,可通过 startForeground() 提升为前台服务优先级较低,绑定组件退出后可能更快被回收
共存场景可与 Bound Service 共存,需同时调用 stopSelf() 和解绑操作才能销毁与 Started Service 共存时,需先解绑所有组件再手动停止服务

涉及的生命周期方法:

生命周期方法触发场景
onCreate()Service 首次创建时调用(仅一次)
onStartCommand()每次通过 startService() 启动时调用
onBind()通过 bindService() 绑定时调用
onUnbind()所有客户端解绑时调用
onDestroy()Service 被销毁前调用(需手动停止或系统回收)

Service 默认运行在主线程,耗时操作需自行创建子线程或使用 IntentService

二、启停 Service

1. 定义 Service 类
继承 Service 类并实现核心方法:

public class MyService extends Service {private static final String TAG = "MyService";@Overridepublic IBinder onBind(Intent intent) {return null; // 非绑定模式时返回 null}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.d(TAG, "Service 启动"); // 执行后台任务return START_STICKY; // 服务终止后自动重启}@Overridepublic void onDestroy() {Log.d(TAG, "Service 销毁");super.onDestroy();}
}

2. 注册 Service

在 AndroidManifest.xml 中添加声明:

<application><service android:name=".MyService" />
</application>

3. 通过 startService() 启动

在 Activity 或其他组件中调用:

Intent serviceIntent = new Intent(this, MyService.class);
startService(serviceIntent); // 启动服务:ml-citation{ref="6,8" data="citationList"}

4. ‌通过 stopService() 或 stopSelf() 停止

stopService(new Intent(this, MyService.class)); // 外部停止
// 或在 Service 内部调用 stopSelf();:ml-citation{ref="6,8" data="citationList"}

三、绑定 Service

1. ‌定义 Bound Service

  • 通过 LocalBinder 返回 Service 实例,实现组件间交互
  • onBind() 返回 IBinder 对象,供客户端绑定
// MyBoundService.java  
public class MyBoundService extends Service {  private final IBinder binder = new LocalBinder();  private static final String TAG = "MyBoundService";  public class LocalBinder extends Binder {  MyBoundService getService() {  return MyBoundService.this;  }  }  @Override  public IBinder onBind(Intent intent) {  Log.d(TAG, "Service 已绑定");  return binder;  }  @Override  public boolean onUnbind(Intent intent) {  Log.d(TAG, "所有客户端已解绑");  return super.onUnbind(intent);  }  // 自定义服务方法(供Activity调用)  public void performTask(String data) {  Log.d(TAG, "执行任务:" + data);  }  
}

2. 注册 Service

在 AndroidManifest.xml 中添加声明:

<application>  <service android:name=".MyBoundService" />  
</application>  

3. Activity 绑定与通信

  • 通过 bindService() 建立绑定
  • ServiceConnection 处理绑定成功/断开事件
  • 绑定后通过 myService 实例直接调用服务方法
  • 必须调用 unbindService() 释放资源,避免内存泄漏
  • 多个组件可绑定同一服务,全部解绑后服务销毁
// MainActivity.java  
public class MainActivity extends AppCompatActivity {  private MyBoundService myService;  private boolean isBound = false;  private ServiceConnection connection = new ServiceConnection() {  @Override  public void onServiceConnected(ComponentName name, IBinder service) {  MyBoundService.LocalBinder binder= (MyBoundService.LocalBinder) service;  myService = binder.getService();  isBound = true;  myService.performTask("Hello from Activity!"); // 调用服务方法  }  @Override  public void onServiceDisconnected(ComponentName name) {  isBound = false;  }  };  @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  // 绑定服务  Intent intent = new Intent(this, MyBoundService.class);  bindService(intent, connection, Context.BIND_AUTO_CREATE);  }  @Override  protected void onDestroy() {  super.onDestroy();  if (isBound) {  unbindService(connection); // 必须解绑避免泄漏  isBound = false;  }  }  
}  

Activity 创建时: bindService() → Service: onCreate() → onBind()

Activity 销毁时: unbindService() → Service: onUnbind() → onDestroy()

四、前台服务

1. 服务端实现

  • Android 8.0+ 必须创建 NotificationChannel,否则通知无法显示
  • 通过 IMPORTANCE_LOW 设置低优先级(无提示音)
  • startForeground() 必须在 onCreate() 或 onStartCommand() 中调用,调用后服务优先级提升,避免被系统轻易回收
  • stopForeground(true) 确保通知栏通知被移除
// ForegroundService.java
public class ForegroundService extends Service {private static final int NOTIFICATION_ID = 1001;private static final String CHANNEL_ID = "foreground_service_channel";@Overridepublic void onCreate() {super.onCreate();createNotificationChannel();startForegroundWithNotification("服务初始化中...");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// 获取 Activity 传递的数据(可选)String inputData = intent != null? intent.getStringExtra("input_data") : null;updateNotification("正在运行: " + inputData);// 模拟耗时任务new Thread(() -> {for (int i = 0; i < 10; i++) {try {Thread.sleep(1000);updateNotification("进度: " + (i + 1) * 10 + "%");} catch (InterruptedException e) {e.printStackTrace();}}stopSelf(); // 任务完成后自动停止服务}).start();return START_STICKY; // 服务被系统杀死后自动重启}private void createNotificationChannel() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {NotificationChannel channel = new NotificationChannel(CHANNEL_ID,"前台服务示例",NotificationManager.IMPORTANCE_LOW);channel.setDescription("用于展示前台服务的持续运行状态");NotificationManager manager= getSystemService(NotificationManager.class);manager.createNotificationChannel(channel);}}private void startForegroundWithNotification(String text) {Intent notificationIntent = new Intent(this, MainActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,PendingIntent.FLAG_IMMUTABLE);Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID).setContentTitle("前台服务示例").setContentText(text).setSmallIcon(R.drawable.ic_notification).setContentIntent(pendingIntent).setOnlyAlertOnce(true) // 避免重复提示音.build();startForeground(NOTIFICATION_ID, notification);}private void updateNotification(String text) {Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID).setContentTitle("前台服务示例").setContentText(text).setSmallIcon(R.drawable.ic_notification).setOnlyAlertOnce(true).build();NotificationManager manager= getSystemService(NotificationManager.class);manager.notify(NOTIFICATION_ID, notification);}@Overridepublic IBinder onBind(Intent intent) {return null; // 无需绑定功能}@Overridepublic void onDestroy() {super.onDestroy();stopForeground(true); // 停止时移除通知}
}

2. 配置清单文件注册服务

<!-- 服务端 AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"><!-- 必须的权限声明,否则startForeground方法不可用 --><uses-permission android:name="android.permission.FOREGROUND_SERVICE"/><application><!-- 服务定义 --><serviceandroid:name=".ForegroundService"android:enabled="true"android:exported="false"android:foregroundServiceType="mediaPlayback"/>  <!-- 按需配置类型 --></application>
</manifest>

3. 客户端调用(Activity)

  • 通过 stopSelf() 或 stopService() 停止服务
// MainActivity.java
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 启动前台服务按钮findViewById(R.id.btn_start).setOnClickListener(v -> {Intent serviceIntent = new Intent(this, ForegroundService.class);serviceIntent.putExtra("input_data", "用户启动任务");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {startForegroundService(serviceIntent); // Android 8.0+ 专用方法} else {startService(serviceIntent);}});// 停止服务按钮findViewById(R.id.btn_stop).setOnClickListener(v -> {Intent serviceIntent = new Intent(this, ForegroundService.class);stopService(serviceIntent);});}
}

4. 客户端配置权限

<!-- 客户端 AndroidManifest.xml -->  
<manifest>  <!-- 添加权限 -->  <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>  <!-- 跨进程调用时添加(可选) -->  <queries>  <package android:name="com.example.service"/>  </queries>  <application>  <!-- 无需声明服务组件 -->  </application>  
</manifest>  

五、远程服务扩展

1. 自定义 Parcelable 对象

// CustomData.java  
package com.example.model;  import android.os.Parcel;  
import android.os.Parcelable;  public class CustomData implements Parcelable {  private String content;  // 构造函数  public CustomData(String content) {  this.content = content;  }  // Parcelable 反序列化构造函数  protected CustomData(Parcel in) {  content = in.readString();  }  // Parcelable CREATOR  public static final Creator<CustomData> CREATOR = new Creator<CustomData>() {  @Override  public CustomData createFromParcel(Parcel in) {  return new CustomData(in);  }  @Override  public CustomData[] newArray(int size) {  return new CustomData[size];  }  };  @Override  public int describeContents() {  return 0;  }  @Override  public void writeToParcel(Parcel dest, int flags) {  dest.writeString(content);  }  // Getter  public String getContent() {  return content;  }  
}  

2. 定义 AIDL 接口

  • AIDL 文件定义跨进程通信的接口方法
  • 支持基本类型、StringListParcelable 等数据类型
  • 需在 AIDL 中显式导入 parcelable 类型
// IRemoteService.aidl  
package com.example.service;  parcelable CustomData;
interface IRemoteService {  int add(int a, int b);  String getData(String input); void sendData(in CustomData data); void registerCallback(IRemoteCallback callback);void unregisterCallback(IRemoteCallback callback);
}  // 回调接口(IRemoteCallback.aidl)
interface IRemoteCallback {void onResult(int result);
}

3. 服务端实现 AIDL 接口

  • 继承 IRemoteService.Stub 实现接口方法
  • 通过 onBind() 返回 IBinder 对象
  • 直接使用 CustomData 对象(已自动反序列化)
  • 服务端通过 RemoteCallbackList 自动清理无效回调,无需手动处理。
  • RemoteCallbackList.register() 会自动去重,多次注册同一回调不会重复触发
public class RemoteService extends Service {  private final IBinder binder = new RemoteBinder();// 使用 RemoteCallbackList 管理跨进程回调(线程安全)private final RemoteCallbackList<IRemoteCallback> callbackList= new RemoteCallbackList<>();private class RemoteBinder extends IRemoteService.Stub {  @Override  public int add(int a, int b) {  int result = a + b;notifyResult(result); // 触发回调通知return result;}  @Override  public String getData(String input) {  return "Processed: " + input;  }  @Override  public void sendData(CustomData data) throws RemoteException {  Log.d(TAG, "收到数据: " + data.getContent());  // 处理数据逻辑  } @Overridepublic void registerCallback(IRemoteCallback callback) {if (callback != null) {callbackList.register(callback);}}@Overridepublic void unregisterCallback(IRemoteCallback callback) {if (callback != null) {callbackList.unregister(callback);}}// 通知所有客户端计算结果private void notifyResult(int result) {int count = callbackList.beginBroadcast();try {for (int i = 0; i < count; i++) {IRemoteCallback callback = callbackList.getBroadcastItem(i);callback.onResult(result); // 跨进程回调}} catch (RemoteException e) {e.printStackTrace(); // 客户端已断开,自动从列表中移除} finally {callbackList.finishBroadcast();}}}  @Override  public IBinder onBind(Intent intent) {  return binder;  }  @Overridepublic void onDestroy() {super.onDestroy();callbackList.kill(); // 清理回调列表}
}  

注意:必须使用 Android 提供的 RemoteCallbackList 管理跨进程回调(自动处理客户端进程死亡情况),普通集合(如 ArrayList)无法正确识别跨进程的 IBinder 对象。

4. 注册 Service(AndroidManifest.xml)

  • android:exported="true" 允许跨进程访问
  • 定义唯一 action 供客户端绑定
  • android:process=":remote" 强制指定独立进程,所有跨进程绑定均指向此进程,复用同一实例
<!-- 服务端AndroidManifest.xml-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"><!-- 声明自定义权限(可选,用于安全控制) --><permissionandroid:name="com.example.permission.REMOTE_SERVICE"android:protectionLevel="signature"/> <!-- 仅允许同签名应用访问 --><!-- 添加前台服务权限(若涉及前台服务) --><uses-permission android:name="android.permission.FOREGROUND_SERVICE"/><application><!-- RemoteService 定义 --><serviceandroid:name=".RemoteService"android:enabled="true"android:exported="true" <!-- 允许跨进程访问 -->android:permission="com.example.permission.REMOTE_SERVICE" <!-- 绑定权限 -->android:process=":remote"> <!-- 指定独立进程,全局唯一 --><intent-filter><action android:name="com.example.service.IRemoteService"/></intent-filter></service></application>
</manifest>

5. 客户端绑定与调用远程服务

  • 通过隐式 Intent 指定服务端包名和 Action
  • 使用 IRemoteService.Stub.asInterface() 转换 IBinder 对象
  • 所有跨进程方法调用需处理 RemoteException
  • 在 onServiceDisconnected() 和 onBindingDied() 中,直接清理本地资源(如置空 remoteService),‌不调用任何远程方法‌。
  • 客户端无需在断开时调用 unregisterCallback(),服务端能正确处理死亡 Binder,其注册的回调会自动从列表中移除。
  • 如果客户端维护了本地回调列表(如 localCallbackList),需在断开时直接清理,无需依赖服务端确认。
public class MainActivity extends AppCompatActivity {  private IRemoteService remoteService;  private boolean isBound = false;  private IRemoteCallback callback = new IRemoteCallback.Stub() {@Overridepublic void onResult(int result) {// 注意:此处运行在 Binder 线程,需切到主线程更新 UInew Handler(Looper.getMainLooper()).post(() -> {textView.setText("计算结果: " + result);});}};// 绑定服务方法(封装复用)private void bindService() {Intent intent = new Intent("com.example.service.IRemoteService");intent.setPackage("com.example.service"); // 显式指定包名// 判断是否 Android 11+ 需要添加 flagsif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {bindService(intent, connection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);} else {bindService(intent, connection, Context.BIND_AUTO_CREATE);}}private ServiceConnection connection = new ServiceConnection() {  @Override  public void onServiceConnected(ComponentName name, IBinder service) {  remoteService = IRemoteService.Stub.asInterface(service);  isBound = true;  try {  remoteService.registerCallback(callback); // 注册回调int result = remoteService.add(3, 5);  Log.d("Client", "Result: " + result);  CustomData data = new CustomData("Hello from Client"); remoteService.sendData(data);} catch (RemoteException e) {  // 远程调用异常捕获e.printStackTrace();  Log.e("Client", "Remote call failed: " + e.getMessage());}  }  @Override  public void onServiceDisconnected(ComponentName name) {  isBound = false; remoteService = null; if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {new Handler(Looper.getMainLooper()).postDelayed(() -> {reconnectAttempts++;Log.w(TAG, "尝试第 " + reconnectAttempts + " 次重连...");bindService(); // 调用绑定方法}, 3000); // 延迟 3 秒后重试(避免频繁请求)} else {Log.e(TAG, "已达到最大重连次数,停止尝试");}}  @Overridepublic void onBindingDied(ComponentName name) {// Android 10+ 新增回调,处理绑定失效场景onServiceDisconnected(name);}};  @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  bindService(); }  @Override  protected void onDestroy() {  super.onDestroy();  try {if (remoteService != null && callback != null) {remoteService.unRegisterCallback(callback); // 主动注销remoteService = null;}} catch (RemoteException e) {e.printStackTrace();}if (isBound) {  unbindService(connection);  isBound = false;  }  }  
}  

6. 客户端声明权限

<!-- 客户端 AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.client"><!-- Android 11+ 跨应用通信需添加 queries(必选) --><queries><!-- 声明目标服务端包名 --><package android:name="com.example.service" /><!-- 若需要调用特定组件(如 Activity)可扩展为 --><!--<intent><action android:name="android.intent.action.VIEW" /><data android:scheme="https" /></intent>--></queries><application><!-- 其他组件声明(如 Activity) --></application>
</manifest>

六、服务保活

方法适用场景厂商兼容性系统限制
前台服务+通知用户感知型任务Android 8+
JobScheduler 定时拉活低频后台任务Android 5+
系统广播监听紧急恢复场景Android 7+
独立进程守护高稳定性要求场景全版本

1. 前台服务 + 通知 (前面已介绍)

  • 使用 startForeground() 提升服务优先级至前台级别
  • Android 9+ 需动态申请 FOREGROUND_SERVICE 权限
public class PersistentService extends Service {@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// 创建前台通知(Android 8.0+ 需通知渠道)Notification notification = new NotificationCompat.Builder(this, "channel_id").setContentTitle("服务运行中").setSmallIcon(R.drawable.ic_notification).build();startForeground(1, notification); // 必须显示通知return START_STICKY; // 服务终止后尝试重启:// ml-citation{ref="1,6" data="citationList"}}
}

2. 粘性服务重启策略

覆盖生命周期方法:

@Override
public void onTaskRemoved(Intent rootIntent) {// 任务被移除时(如用户划掉最近任务)触发重启Intent restartIntent = new Intent(this, PersistentService.class);restartIntent.setPackage(getPackageName());startService(restartIntent);super.onTaskRemoved(rootIntent);
}@Override
public void onDestroy() {// 服务被系统杀死时触发重启逻辑// 发送广播,需要注册一个广播接收器sendBroadcast(new Intent("RESTART_SERVICE_ACTION")); super.onDestroy();
}

注册广播接收器,通过广播重新拉起服务 :

<receiver android:name=".RestartReceiver"><intent-filter><action android:name="RESTART_SERVICE_ACTION" /></intent-filter>
</receiver>

频繁调用 startService() 可能导致 ANR,建议结合 JobScheduler 优化

3. 系统广播监听

听高频触发广播,利用网络变化、解锁等事件触发服务重启。

<receiver android:name=".SystemEventReceiver"><intent-filter><action android:android:name="android.intent.action.BOOT_COMPLETED" /><action android:name="android.net.conn.CONNECTIVITY_CHANGE" /><action android:name="android.intent.action.USER_PRESENT" /></intent-filter>
</receiver>

4. 进程守护与JobScheduler

独立进程运行,减少主进程崩溃对服务的影响。

<service android:name=".PersistentService"android:process=":persistent_process" />

JobScheduler 定时唤醒,定期检查服务状态并拉起。

ComponentName serviceComponent = new ComponentName(this, PersistentService.class);
JobInfo jobInfo = new JobInfo.Builder(1, serviceComponent).setPeriodic(15 * 60 * 1000)  // 15分钟间隔.setPersisted(true)  // 设备重启后保持任务.build();
JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);

七、服务启动方法混用

1. startService() 重复调用

  • 首次调用‌:触发 onCreate() → onStartCommand()
  • 后续调用‌:仅触发 onStartCommand()onCreate() 不再执行
// 第一次调用
startService(intent); // onCreate() -> onStartCommand()// 第二次调用
startService(intent); // 仅 onStartCommand()

2. bindService() 重复调用

  • 首次绑定‌:触发 onCreate() → onBind()
  • 后续绑定‌:若 Service 已存在,直接返回已创建的 IBinder 对象,不再触发 onBind()
// 第一次绑定
// onCreate() -> onBind()
bindService(intent, conn, BIND_AUTO_CREATE); // 第二次绑定(同一进程)
// 无生命周期方法调用,复用已有 IBinder
bindService(intent, conn2, BIND_AUTO_CREATE); 

不同进程再次绑定‌:

  • 同一 Service 实例‌:若 Service 已在独立进程运行,后续绑定直接复用已有实例,‌不再触发 onCreate() 和 onBind()‌,仅通过 ServiceConnection 返回 IBinder 代理对象。
  • 新 Service 实例‌:若应用配置多进程且未声明 android:process,不同组件进程可能触发多个 Service 实例(需避免此设计

3. 混合调用场景

 startService() 后 bindService():

Service 生命周期持续到 unbindService() 和 stopService()/stopSelf() 均被调用

startService(intent); // onCreate() -> onStartCommand()
bindService(intent, conn); // onBind(),Service 已存在无需创建

同理,先bindService()后startService()

bindService(intent, conn); // 创建 Service 实例,onCreate() → onBind()
startService(intent); // onStartCommand(),Service 已存在无需创建

混合调用时需同时调用 stopService() 和 unbindService() 才能销毁 Service

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/81055.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/81055.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/81055.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pytest 技术总结

目录 一 pytest的安装&#xff1a; 二 pytest有三种启动方式&#xff1a; 三 用例规则&#xff1a; 四 配置框架&#xff1a; 一 pytest的安装&#xff1a; pip install pytest # 安装 pip install pytest -U # 升级到最新版 二 pytest有三种启动方式&#xff1a; 1…

redis 有序集合zrange和zrangebyscore的区别

起因是查询数据&#xff0c;用了zrangebyscore 但是一直显示没数据 具体命令zrangebyscore key 0 -1 withscores, 原有印象中一直是这么用的&#xff0c;但是突然查不出来了&#xff0c; 于是搜了下问题所在。 通过分数查看 不能用0和-1表示最小和最大&#xff0c;只能用分数来…

Tableau 基础表制作

目录 1.数据连接 2. 数据可视化 3. 基础表制作 3.1 对比分析&#xff1a;比大小 1. 柱状图 2. 条形图 3. 热力图 4. 气泡图 5. 词云 3.2 变化分析&#xff1a;看趋势 1. 折线图 2. 面积图 3.3 构成分析&#xff1a;看占比 1. 饼图 2. 树地图 3. 堆积图 3.4 关…

反序列化漏洞1

一、PHP类与对象 1. 类 概念理解: 类是共享相同结构和行为的对象的集合&#xff0c;可以理解为特征的提取。例如将耳朵长、尾巴短、红眼睛、吃胡萝卜、蹦跳行走的动物特征抽象为"兔子"类。代码结构: 使用class关键字定义类类名遵循大驼峰命名法包含成员变量(属性)和…

为什么要对 ACI 网络进行升级?

一、硬件演进 1. 交换机接口 前面板接口由 1/10G 升级至 10/25/100G fabric 上行链路 40G 升级至 100/400G 2. 交换机角色 交换机可以是 spine 或者 leaf,而不是固定角色 3. EOS APIC-SERVER-M2/L2 2024年6月30日 EOS,替换设备为 APIC-SERVER-M4/L4 二、网络升级参考文…

DeepSeek+Cline:开启自动化编程新纪元

目录 一、引言&#xff1a;AI 编程时代的曙光二、认识 DeepSeek 和 Cline2.1 DeepSeek 是什么2.2 Cline 详解2.3 两者结合的魅力 三、DeepSeek Cline 安装与配置全流程3.1 安装 VS Code3.2 安装 Cline 插件3.3 获取 DeepSeek API Key3.4 配置 Cline 与 DeepSeek 连接 四、实战演…

【展位预告】正也科技将携营销精细化管理解决方案出席中睿营销论坛

在医药行业面临政策深化、技术迭代、全球化竞争的多重挑战下&#xff0c;第二届中睿医药健康生态生长力峰会暨第三十五届中睿医药营销论坛将于广州盛大启幕。5月19-20日本次峰会以“聚焦政策变革、把握产业趋势、构建生态共赢”为核心&#xff0c;旨在通过全产业链资源整合与创…

【深度学习】评估模型复杂度:GFLOPs与Params详解

评估模型复杂度&#xff1a;GFLOPs与Params详解 在深度学习模型设计与优化过程中&#xff0c;GFLOPs和Params是论文中两个重要的评估指标&#xff0c;它们分别衡量模型的计算复杂度和参数量。本文将详细介绍这两个概念及其在实践中的应用。 1. Params&#xff1a;模型参数量 …

Go语言->练习6例

1.go语言的接口实现 接口&#xff08;interface&#xff09;是一种类型&#xff0c;它定义了一组方法的集合。任何类型只要实现了接口中定义的所有方法&#xff0c;就被认为实现了该接口。 在Go语言中&#xff0c;使用接口的最佳实践可以提高代码的可读性、可维护性和灵活性。…

Drivestduio 代码笔记与理解

Rigid Node: 表示 car或者trucks Deformable Node : 表示一些 分布之外的 non-rigid 的运动物体&#xff0c; 比如远处的行人等和Cyclist。 在 load_objects 会读取每一个 dynamic objects 的 bounding box’的信息&#xff0c;具体如下&#xff1a; frame_instances 记录了每…

《算法笔记》10.5小节——图算法专题->最小生成树 问题 E: Jungle Roads

题目描述 The Head Elder of the tropical island of Lagrishan has a problem. A burst of foreign aid money was spent on extra roads between villages some years ago. But the jungle overtakes roads relentlessly, so the large road network is too expensive to mai…

【音视频】SDL简介

官网&#xff1a;官网 文档&#xff1a;文档 SDL&#xff08;Simple DirectMedia Layer&#xff09;是一套开放源代码的跨平台多媒体开发库&#xff0c;使用C语言写成。SDL提供数种控制图像、声音、输出入的函数&#xff0c;让开发者只 要用相同或是相似的代码就可以开发出跨多…

SpringBoot + SSE 实时异步流式推送

前言 在当今数字化时代&#xff0c;实时数据处理对于企业的决策和运营至关重要。许多业务场景需要及时响应数据库中的数据变化&#xff0c;例如电商平台实时更新库存、金融系统实时监控交易数据等。 本文将详细介绍如何通过Debezium捕获数据库变更事件&#xff0c;并利用Serv…

ADS1299模拟前端(AFE)代替芯片——LHE7909

在现代医疗科技的飞速发展中&#xff0c;精确的生物电势测量设备变得越来越重要。领慧立芯推出的LHE7909&#xff0c;是一款专为心电图&#xff08;ECG&#xff09;和其他生物电势测量设计的低噪声24位模数转换器&#xff08;ADC&#xff09;&#xff0c;为医疗设备制造商提供了…

如何实现Redis和Mysql中数据双写一致性

一、引言 今天我们来聊聊一个在分布式系统中非常常见但又十分棘手的问题——Redis与MySQL之间的双写一致性。我们在项目中多多少少都遇到过类似的困扰&#xff0c;缓存是用Redis&#xff0c;数据库是用MySQL&#xff0c;但如何确保两者之间的数据一致性呢&#xff1f;接下来我…

面试篇 - Transformer前馈神经网络(FFN)使用什么激活函数?

1. FFN结构分解 原始Transformer的FFN层 FFN(x) max(0, xW₁ b₁)W₂ b₂ # 原始论文公式 输入&#xff1a;自注意力层的输出 x&#xff08;维度 d_model512&#xff09; 扩展层&#xff1a;xW₁ b₁&#xff08;扩展为 d_ff2048&#xff09; 激活函数&#xff1a;Re…

基于Python Flask的深度学习电影评论情感分析可视化系统(2.0升级版,附源码)

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

前端vue2修改echarts字体为思源黑体-避免侵权-可以更换为任意字体统一管理

1.下载字体 npm install fontsource/noto-sans-sc 不知道为什么我从github上面下载的不好使&#xff0c;所以就用了npm的 2.引用字体 import fontsource/noto-sans-sc; 在入口文件-main.js中引用 3.设置echats模板样式 import * as echarts from echarts; // 在import的后…

51c自动驾驶~合集37

我自己的原文哦~ https://blog.51cto.com/whaosoft/13878933 #DETR->DETR3D->Sparse4D 走向长时序稀疏3D目标检测 一、DETR 图1 DETR架构 DETR是第一篇将Transformer应用到目标检测方向的算法。DETR是一个经典的Encoder-Decoder结构的算法&#xff0c;它的骨干网…

【MongoDB篇】MongoDB的集合操作!

目录 引言第一节&#xff1a;集合的“诞生”——自动出现还是手动打造&#xff1f;&#x1f914;第二节&#xff1a;集合的“查阅”——看看这个数据库里有哪些柜子&#xff1f;&#x1f4c2;&#x1f440;第三节&#xff1a;集合的“重命名”——给文件柜换个名字&#xff01;…