熊熊出没 发表于 2024-6-24 21:43:10

深入分析 Android Service (完)

深入分析 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 被创建时调用。通常在这里初始化任何必要的资源。
@Override
public void onCreate() {
    super.onCreate();
    // 初始化资源,如线程池、数据库连接等
}
2.2 onStartCommand(Intent intent, int flags, int startId)

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

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

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

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

在 Service 被烧毁前调用。通常在这里清理全部资源。
@Override
public void onDestroy() {
    super.onDestroy();
    // 释放资源
}
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 创建前台服务

public class ForegroundService extends Service {
    @Override
    public void onCreate() {
      super.onCreate();
      Notification notification = createNotification();
      startForeground(1, notification);
    }

    private Notification createNotification() {
      NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
      String channelId = "foreground_service_channel";
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(channelId, "Foreground Service Channel", NotificationManager.IMPORTANCE_DEFAULT);
            notificationManager.createNotificationChannel(channel);
      }
      NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
                .setContentTitle("Foreground Service")
                .setContentText("Service is running in the foreground")
                .setSmallIcon(R.drawable.ic_service_icon);
      return builder.build();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
      // 处理业务逻辑
      return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
      return null;
    }

    @Override
    public void onDestroy() {
      super.onDestroy();
      stopForeground(true);
    }
}
5.2 启动前台服务

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

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

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

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

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

7.1 服务端代码(Messenger)

public class MessengerService extends Service {
    static final int MSG_SAY_HELLO = 1;

    class IncomingHandler extends Handler {
      @Override
      public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                  Toast.makeText(getApplicationContext(), "Hello!", Toast.LENGTH_SHORT).show();
                  break;
                default:
                  super.handleMessage(msg);
            }
      }
    }

    final Messenger messenger = new Messenger(new IncomingHandler());

    @Override
    public IBinder onBind(Intent intent) {
      return messenger.getBinder();
    }
}
7.2 客户端代码(Messenger)

public class MainActivity extends AppCompatActivity {
    Messenger messenger = null;
    boolean isBound = false;

    private ServiceConnection connection = new ServiceConnection() {
      @Override
      public void onServiceConnected(ComponentName name, IBinder service) {
            messenger = new Messenger(service);
            isBound = true;
      }

      @Override
      public void onServiceDisconnected(ComponentName name) {
            messenger = null;
            isBound = false;
      }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      Intent intent = new Intent(this, MessengerService.class);
      bindService(intent, connection, Context.BIND_AUTO_CREATE);

      Button sendButton = findViewById(R.id.sendButton);
      sendButton.setOnClickListener(v -> {
            if (isBound) {
                Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
                try {
                  messenger.send(msg);
                } catch (RemoteException e) {
                  e.printStackTrace();
                }
            }
      });
    }

    @Override
    protected void onDestroy() {
      super.onDestroy();
      if (isBound) {
            unbindService(connection);
            isBound = false;
      }
    }
}
7.3 服务端代码(AIDL)

public class MyAidlService extends Service {
    private final IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
      @Override
      public int add(int a, int b) {
            return a + b;
      }
    };

    @Override
    public IBinder onBind(Intent intent) {
      return binder;
    }
}
7.4 客户端代码(AIDL)

public class MainActivity extends AppCompatActivity {
    IMyAidlInterface myAidlService = null;
    boolean isBound = false;

    private ServiceConnection connection = new ServiceConnection() {
      @Override
      public void onServiceConnected(ComponentName name, IBinder service) {
            myAidlService = IMyAidlInterface.Stub.asInterface(service);
            isBound = true;
      }

      @Override
      public void onServiceDisconnected(ComponentName name) {
            myAidlService = null;
            isBound = false;
      }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      Intent intent = new Intent(this, MyAidlService.class);
      bindService(intent, connection, Context.BIND_AUTO_CREATE);

      Button addButton = findViewById(R.id.addButton);
      addButton.setOnClickListener(v -> {
            if (isBound) {
                try {
                  int result = myAidlService.add(5, 3);
                  Toast.makeText(MainActivity.this, "Result: " + result, Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                  e.printStackTrace();
                }
            }
      });
    }

    @Override
    protected void onDestroy() {
      super.onDestroy();
      if (isBound) {
            unbindService(connection);
            isBound = false;
      }
    }
}
8. 总结

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 深入分析 Android Service (完)