深入分析 Android Service (完)

熊熊出没  论坛元老 | 2024-6-24 21:43:10 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1020|帖子 1020|积分 3060

深入分析 Android Service (完)

1. Service 的生命周期管理

Service 的生命周期管理是确保 Service 能够正确启动、运行、制止和清理资源的关键。理解 Service 的生命周期方法可以帮助开发者更好地管理和优化 Service。
2. Service 的生命周期方法

Service 的主要生命周期方法包括:

  • onCreate()
  • onStartCommand(Intent intent, int flags, int startId)
  • onBind(Intent intent)
  • onUnbind(Intent intent)
  • onRebind(Intent intent)
  • onDestroy()
2.1 onCreate()

在 Service 被创建时调用。通常在这里初始化任何必要的资源。
  1. @Override
  2. public void onCreate() {
  3.     super.onCreate();
  4.     // 初始化资源,如线程池、数据库连接等
  5. }
复制代码
2.2 onStartCommand(Intent intent, int flags, int startId)

在每次通过 startService() 方法启动 Service 时调用。此方法是处理实际业务逻辑的主要入口。返回值决定系统怎样在服务因内存不敷而被杀死后重启它。
  1. @Override
  2. public int onStartCommand(Intent intent, int flags, int startId) {
  3.     // 处理业务逻辑,如下载文件、播放音乐等
  4.     return START_STICKY;  // START_NOT_STICKY, START_REDELIVER_INTENT, or START_STICKY_COMPATIBILITY
  5. }
复制代码
2.3 onBind(Intent intent)

在客户端绑定到 Service 时调用。返回一个 IBinder 对象,用于与客户端通信。
  1. @Override
  2. public IBinder onBind(Intent intent) {
  3.     // 返回通信接口
  4.     return binder;
  5. }
复制代码
2.4 onUnbind(Intent intent)

在全部客户端都解绑时调用。通常在这里清理与绑定相关的资源。
  1. @Override
  2. public boolean onUnbind(Intent intent) {
  3.     // 清理绑定相关资源
  4.     return super.onUnbind(intent);
  5. }
复制代码
2.5 onRebind(Intent intent)

在之前调用了 onUnbind() 后,新的客户端再次绑定到 Service 时调用。
  1. @Override
  2. public void onRebind(Intent intent) {
  3.     super.onRebind(intent);
  4. }
复制代码
2.6 onDestroy()

在 Service 被烧毁前调用。通常在这里清理全部资源。
  1. @Override
  2. public void onDestroy() {
  3.     super.onDestroy();
  4.     // 释放资源
  5. }
复制代码
3. Service 重启策略

onStartCommand 方法的返回值决定了当 Service 因系统内存不敷被杀死后,系统怎样重启它:


  • START_STICKY:服务被系统制止后会主动重启。Intent 不会保留,意味着数据不会保留,但服务会继承运行。
  • START_NOT_STICKY:服务被系统制止后不会主动重启,除非有新的 Intent。
  • START_REDELIVER_INTENT:服务被系统制止后会主动重启,并重传末了一个 Intent。
  • START_STICKY_COMPATIBILITY:雷同于 START_STICKY,但用于兼容低版本。
4. 利用 Service 进行前台任务

为了确保 Service 在后台运行时不被系统制止,可以将 Service 提升为前台服务。这可以通过调用 startForeground() 方法实现,并提供一个连续显示的通知。
5. 实现前台服务示例

5.1 创建前台服务

  1. public class ForegroundService extends Service {
  2.     @Override
  3.     public void onCreate() {
  4.         super.onCreate();
  5.         Notification notification = createNotification();
  6.         startForeground(1, notification);
  7.     }
  8.     private Notification createNotification() {
  9.         NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  10.         String channelId = "foreground_service_channel";
  11.         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  12.             NotificationChannel channel = new NotificationChannel(channelId, "Foreground Service Channel", NotificationManager.IMPORTANCE_DEFAULT);
  13.             notificationManager.createNotificationChannel(channel);
  14.         }
  15.         NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
  16.                 .setContentTitle("Foreground Service")
  17.                 .setContentText("Service is running in the foreground")
  18.                 .setSmallIcon(R.drawable.ic_service_icon);
  19.         return builder.build();
  20.     }
  21.     @Override
  22.     public int onStartCommand(Intent intent, int flags, int startId) {
  23.         // 处理业务逻辑
  24.         return START_STICKY;
  25.     }
  26.     @Override
  27.     public IBinder onBind(Intent intent) {
  28.         return null;
  29.     }
  30.     @Override
  31.     public void onDestroy() {
  32.         super.onDestroy();
  33.         stopForeground(true);
  34.     }
  35. }
复制代码
5.2 启动前台服务

在 Activity 中启动前台服务:
  1. Intent intent = new Intent(this, ForegroundService.class);
  2. startService(intent);
复制代码
6. Service 的优化和调试

为了优化 Service 的性能和可靠性,可以采用以下方法:
6.1 利用 JobScheduler 替代传统 Service

对于需要在特定条件下运行的任务,保举利用 JobScheduler,它可以根据系统资源和条件优化任务的执行时间。
  1. JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
  2. JobInfo jobInfo = new JobInfo.Builder(1, new ComponentName(this, MyJobService.class))
  3.         .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
  4.         .setRequiresCharging(true)
  5.         .build();
  6. jobScheduler.schedule(jobInfo);
复制代码
6.2 利用 WorkManager 处理后台任务

WorkManager 提供了一种当代化的任务调理机制,实用于需要包管任务执行的场景。它可以主动处理任务的重试和束缚条件。
  1. OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(MyWorker.class)
  2.         .setConstraints(new Constraints.Builder().setRequiresCharging(true).build())
  3.         .build();
  4. WorkManager.getInstance(this).enqueue(workRequest);
复制代码
6.3 调试和监控

利用 StrictMode 检测潜伏的性能问题,如磁盘读写和网络访问:
  1. if (BuildConfig.DEBUG) {
  2.     StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
  3.             .detectAll()
  4.             .penaltyLog()
  5.             .build());
  6.     StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
  7.             .detectAll()
  8.             .penaltyLog()
  9.             .build());
  10. }
复制代码
利用 Android Studio 的 Profiler 工具监控 Service 的 CPU、内存和网络利用情况,以识别息争决性能瓶颈。
7. 示例代码汇总

7.1 服务端代码(Messenger)

  1. public class MessengerService extends Service {
  2.     static final int MSG_SAY_HELLO = 1;
  3.     class IncomingHandler extends Handler {
  4.         @Override
  5.         public void handleMessage(Message msg) {
  6.             switch (msg.what) {
  7.                 case MSG_SAY_HELLO:
  8.                     Toast.makeText(getApplicationContext(), "Hello!", Toast.LENGTH_SHORT).show();
  9.                     break;
  10.                 default:
  11.                     super.handleMessage(msg);
  12.             }
  13.         }
  14.     }
  15.     final Messenger messenger = new Messenger(new IncomingHandler());
  16.     @Override
  17.     public IBinder onBind(Intent intent) {
  18.         return messenger.getBinder();
  19.     }
  20. }
复制代码
7.2 客户端代码(Messenger)

  1. public class MainActivity extends AppCompatActivity {
  2.     Messenger messenger = null;
  3.     boolean isBound = false;
  4.     private ServiceConnection connection = new ServiceConnection() {
  5.         @Override
  6.         public void onServiceConnected(ComponentName name, IBinder service) {
  7.             messenger = new Messenger(service);
  8.             isBound = true;
  9.         }
  10.         @Override
  11.         public void onServiceDisconnected(ComponentName name) {
  12.             messenger = null;
  13.             isBound = false;
  14.         }
  15.     };
  16.     @Override
  17.     protected void onCreate(Bundle savedInstanceState) {
  18.         super.onCreate(savedInstanceState);
  19.         setContentView(R.layout.activity_main);
  20.         Intent intent = new Intent(this, MessengerService.class);
  21.         bindService(intent, connection, Context.BIND_AUTO_CREATE);
  22.         Button sendButton = findViewById(R.id.sendButton);
  23.         sendButton.setOnClickListener(v -> {
  24.             if (isBound) {
  25.                 Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
  26.                 try {
  27.                     messenger.send(msg);
  28.                 } catch (RemoteException e) {
  29.                     e.printStackTrace();
  30.                 }
  31.             }
  32.         });
  33.     }
  34.     @Override
  35.     protected void onDestroy() {
  36.         super.onDestroy();
  37.         if (isBound) {
  38.             unbindService(connection);
  39.             isBound = false;
  40.         }
  41.     }
  42. }
复制代码
7.3 服务端代码(AIDL)

  1. public class MyAidlService extends Service {
  2.     private final IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
  3.         @Override
  4.         public int add(int a, int b) {
  5.             return a + b;
  6.         }
  7.     };
  8.     @Override
  9.     public IBinder onBind(Intent intent) {
  10.         return binder;
  11.     }
  12. }
复制代码
7.4 客户端代码(AIDL)

  1. public class MainActivity extends AppCompatActivity {
  2.     IMyAidlInterface myAidlService = null;
  3.     boolean isBound = false;
  4.     private ServiceConnection connection = new ServiceConnection() {
  5.         @Override
  6.         public void onServiceConnected(ComponentName name, IBinder service) {
  7.             myAidlService = IMyAidlInterface.Stub.asInterface(service);
  8.             isBound = true;
  9.         }
  10.         @Override
  11.         public void onServiceDisconnected(ComponentName name) {
  12.             myAidlService = null;
  13.             isBound = false;
  14.         }
  15.     };
  16.     @Override
  17.     protected void onCreate(Bundle savedInstanceState) {
  18.         super.onCreate(savedInstanceState);
  19.         setContentView(R.layout.activity_main);
  20.         Intent intent = new Intent(this, MyAidlService.class);
  21.         bindService(intent, connection, Context.BIND_AUTO_CREATE);
  22.         Button addButton = findViewById(R.id.addButton);
  23.         addButton.setOnClickListener(v -> {
  24.             if (isBound) {
  25.                 try {
  26.                     int result = myAidlService.add(5, 3);
  27.                     Toast.makeText(MainActivity.this, "Result: " + result, Toast.LENGTH_SHORT).show();
  28.                 } catch (RemoteException e) {
  29.                     e.printStackTrace();
  30.                 }
  31.             }
  32.         });
  33.     }
  34.     @Override
  35.     protected void onDestroy() {
  36.         super.onDestroy();
  37.         if (isBound) {
  38.             unbindService(connection);
  39.             isBound = false;
  40.         }
  41.     }
  42. }
复制代码
8. 总结

通过合理计划和优化 Android Service,可以确保应用在后台高效、稳定地运行,提供精良的用户体验。希望本系列文章能够帮助开发者更深入地理解 Service 的工作机制和优化策略,为开发高质量的 Android 应用提供参考和指导。
欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

熊熊出没

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表