《第一行代码》第二版学习笔记(9)——服务

一、线程

android不允许在子线程中更新IU操作

二、解决异步消息处理机制

1、消息组成

  • Message:在线程之间传递消息
  • Handler:发送(SendMessage)和处理消息(handleMessage())
  • MessageQueue:存放所有通过Handler发送的消息
  • Looper:每个线程中MessageQueuede的管家,调用Looper的loop()方法后,就会进入到一个无线循环中,每当MessageQueue有消息时将它取出,传递到Handler的handleMessage()方法当中。

2、AsyncTask

AsyncTask是一个抽象类,子类继承AsyncTask时指定为3个泛型参数(也可以传void):

  • param:在执行AsyncTask时需要传入的参数,可用于在后台任务中使用
  • Progress:后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定泛型作为进度单位
  • Result:指定的泛型作为返回值

经常需要重写的方法

  • onPreExecute:后台任务开始执行调度之前,用于进行界面上的初始化操作。
  • doInBackground:这个方法中的所有代码都会在子线程中执行,在这处理所有耗时的任务。这个方法中不可以进行UI操作
  • onProgressUpdate:在这个方法中可以对UI进行操作
  • onPostExecute(Result):当后台任务执行完毕通过return语句返回时,这个方法很快就会被调用。执行一些任务的收尾工作。

三、Service

1、启动和停止服务

  • 定义服务
    在这里插入图片描述
if (v.getId() == R.id.start_service){
  Intent startIntent = new Intent(this,MyService.class);
      startService(startIntent);
 }else if (v.getId() == R.id.stop_service){
      Intent stopIntent = new Intent(this,MyService.class);
      stopService(stopIntent);
  }

2、活动和服务通信

比如希望在服务里提供一个下载文件的功能

  • 在服务中新建一个DownloadBinder类继承Binder,在这个类的内部提供一个下载和显示进度的方法。
 class DownloadBinder extends Binder{

        public void startDownload(){
            Log.d(TAG,"startDownload executed");
        }

        public int getProgress(){
            Log.d(TAG,"getProgress executed");
            return 0;
        }
    }

  • 在服务中创建这个类的实例,然后在onBind方法中返回这个实例
   @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        //throw new UnsupportedOperationException("Not yet implemented");
        return mBinder;
    }

  • 在活动中创建ServiceConnection 匿名类,在类的onServiceConnected方法中通过向下转型得到了DownloadBinder的实例。
//    服务和活动绑定的解绑的时候用
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            downloadBinder = (MyService.DownloadBinder) service;
            downloadBinder.startDownload();
            downloadBinder.getProgress();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
  • 在活动中定义一个 ServiceConnection 对象和一个 boolean 变量用于跟踪服务是否已绑定, MyService.LocalBinder是服务中的类,可以通过这个类在活动中调用服务中的方法
private MyService myService;
private boolean isServiceBound = false;

private ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        MyService.LocalBinder binder = (MyService.LocalBinder) iBinder;
        myService = binder.getService();
        isServiceBound = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        isServiceBound = false;
    }
};
  • 接下来,在活动的 onCreate() 方法中绑定服务:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 创建意图以绑定服务
    Intent intent = new Intent(this, MyService.class);
    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
  • 最后,在活动销毁时解绑服务:
@Override
protected void onDestroy() {
    super.onDestroy();

    if (isServiceBound) {
        unbindService(serviceConnection);
        isServiceBound = false;
    }
}

3、服务的生命周期

在Android中,服务(Service)是一种可以在后台执行长时间运行操作的组件,它没有用户界面。服务的生命周期包括以下几个关键方法:

  • onCreate():在服务被创建时调用。该方法只会被调用一次,用于进行一次性的初始化操作。
  • onStartCommand():在每次通过 startService() 方法启动服务时调用。该方法是服务的主要入口点,用于处理启动服务的请求,并执行相应的操作。它返回一个整数值,用于指定服务的行为,如何处理请求以及是否在服务被终止后重新启动。
  • onBind():在通过 bindService() 方法绑定服务时调用。该方法返回一个 IBinder 对象,用于提供与活动(或其他组件)进行通信的接口。如果服务不提供绑定功能,可以返回 null。
  • onUnbind():在通过 unbindService() 方法解绑服务时调用。该方法可以执行一些清理操作,如释放资源或取消相关的注册。如果返回 true,表示允许重新绑定该服务;如果返回 false,表示不允许重新绑定。
  • onDestroy():在服务被销毁时调用。该方法在服务即将被销毁时执行一些清理操作,释放资源等。在该方法执行后,服务将不再可用。

注:根据Android系统的机制,一个服务只要被启动或者绑定了之后,就会一直处于运行状态,必须要让两种条件同时不满足,服务才会被销毁。

4、创建前台服务

在 targetSdkVersion >= 34 的情况下,必须为应用内的每个前台服务(Foreground Service)指定至少一种前台服务类型。
使用时需要在 Manifest 文件中申请 android.permission.FOREGROUND_SERVICE 权限。service标签中的属性foregroundServiceType要和该权限对应。

   <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <!-- android14前台常住服务权限-->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>

      <service
            android:name=".MyService"
            android:foregroundServiceType="specialUse"
            android:enabled="true"
            android:exported="true" />

在这里插入图片描述
让该服务变为一个前台服务:

 startForeground(1,notification);

5、使用IntentService

IntentService 让服务在子线程中运行

四、服务的最佳实践

报错:使用书籍提供的下载链接启动下载就失败,貌似是无权限访问,更换一个下载链接即可。

  • 14
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值