【Android基础】第一行代码-Service学习笔记

基础概念

服务常被用作去执行不需要与用户交互而且需要长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者打开了另一个应用程序,服务依旧可以保持正常运行。

android多线程

当我们执行一些耗时操作,比如发送网络请求,如果不把这类操作放到子线程里去执行,会导致主线程被阻塞。

基本使用方法

new Thread(new Runnable(){
    @Override
    public void run(){
    //处理逻辑
    }
}).start();

在子线程中更新UI

在android里面如果需要更新UI元素,则必须要在主线程中进行,否则会出现异常。对于这一问题android给出了一套异步消息处理机制。

//用于接受消息,并在主线程里面进行处理
private Handler handler=new Handler(){
    public void handleMessage(Message msg){
        switch(msg.what){
            case UPDATE_TEXT:
                //进行相关UI操作
                break;
        }
    }
}

//在子线程里面发送消息
public void test(){
    new Thread(new Runnable(){
        @Override
        public void run(){
        //逻辑处理
            Message message=new Message();
            message.what=UPDATE_TEXT;
            handler.sendMessage(message); //将message发送出去
        }
    })
}

异步消息处理主要由四个部分组成:

  • Message 在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程间交换数据。

  • Handler主要用于发送消息和处理消息。发送消息用Handler的sendMessage()方法,最终会传递到Handler的handlerMessage()方法中进行处理

  • MessageQueue消息队列,主要用于存放所有通过Handler发送的消息。每个线程中只有一个MessageQueue对象

  • Looper是每个线程中MessageQueue的管家,调用Looper loop()方法后会进入到一个无限的循环中,每当发现MessageQueue中存在一条消息,就会将它去除,并传递到Handler的handlerMessage方法中。每个线程中只有一个Looper对象。

使用AsyncTask

AsyncTask背后实现原理也是基于异步消息处理机制的,只是Android做了封装。

public class DownloadImageTask extends AsyncTask<Void, Integer, Boolean> {
    //第一个Void是执行AsyncTask需要传入的参数
    //Integer是进度
    //Boolean是执行结果
    
    @Override
    onPreExecute()
    //在后台任务开始执行前调用,用于进行一些页面初始化工作
    
    @Override
    doInBackground()
    //这个方法中所有代码在子线程中执行,处理一些耗时的任务。return返回执行结果,如果第三个泛型参数设置Void则不返回执行结果
    
    @Override
    onProgressUpdate(...)
    //该方法携带的参数就是后台任务中传递过来的,在这个方法里面可以对UI进行操作,利用参数中传来的数值对界面元素进行更新
    
    @Override
    onPostExecute(Result)
    //后台任务执行完毕后通过return返回,这个方法就会被调用,可以根据返回的数据做一些UI操作,比如关闭加载框之类的 
}

 

服务的基本用法

创建服务时两个关键字

exported表示是否允许除了当前程序以外其他程序访问这个服务

Enabled表示是否启用这个服务

public class MyService extends Service{

}

 

生命周期

onCreate():在服务创建的时候调用

onStartCommand():在服务启动的时候调用

  • START_STICKY:若服务进程被杀死,系统会自动重建服务并重新调用 onStartCommand()。如果无待处理的 Intent,onStartCommand() 的 intent 参数为 null,需做判空处理。

  • START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务

  • START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入

  • START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

onBind():绑定服务 bindService时调用

onDestroy():在服务销毁的时候调用

启动、关闭服务

Intent startIntent=new Intent(this,MyService.class);
startService(startIntent);

Intent stopIntent=new Intent(this,MyService.class);
stopService(stopIntent);

每个服务只会存在一个实例,所以不管执行了几遍startService,只用执行一次stopService即可停止服务

活动和服务间的通信

使用场景:比如service提供一个下载功能,在活动中可以决定何时开始这个功能,以及随时查看进度

public class MyService extends Service{
    private DownLoadBinder mBinder=new DownLoadBinder();
    class DownLoadBinder extends Binder{
       //提供两个方法 开始下载 查看下载进度
       public void startDownLoad{
       
       }
       
       public int getProgress{
           return 0;
       }
    }
    
    @Override
    public IBinder onBind(Intent intent){
        return mBinder;
    }
}
public MainActivity extends AppCompatActivity{
    private MyService.DownLoadBinder downloadBinder;
    private ServiceConnection connection=new ServiceConnection(){

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            downloadBinder=(MyService.DownLoadBinder)service;
            downloadBinder.startDownLoad();
            downloadBinder.getProgress();
        }
    
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    };
    
    //在某一时机绑定服务
    Intent bindIntent=new Intent(this,MyService.class);
    bindService(bindIntent,connection,BIND_AUTO_CREATE);
    //在活动和服务绑定后自动创建服务,调用服务的onCreate()方法
    
    //在某一时机解绑服务
    unbindService(connection)
}

activity中执行bindService->Service回调 onBind 返回一个IBinder对象->可以跟上述例子一样向下转型拿到实例

startService->stopService bindService->unbindService onDestroy调用

但如果既调用了startService 又调用了bindService 此时要调用stopService和unbindService onDestroy才会调用

前台服务

前台服务会有一个正在运行的图标在系统的状态栏。

public static void showServiceNotice(Service service) {

    Intent intent = new Intent(AMApp.getInstance(), MainActivity.class);
    PendingIntent pendingIntent= PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
    //PendingIntent.FLAG_UPDATE_CURRENT 如果已存在同类型的 PendingIntent,则保留该 PendingIntent,但将其附加的 Intent 数据替换为最新的。
    //PendingIntent.FLAG_IMMUTABLE声明该 PendingIntent 不可被接收方修改
    
    builder.setContentTitle(noticeTitle)
            .setContentText(noticeContent)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(pendingIntent)
            .setWhen(System.currentTimeMillis())
            .setOngoing(true)
            .setSilent(true)
            .setAutoCancel(false);
    Notification notification = builder.build();
    int notificationID = 1111;
    notificationManager.notify(notificationID, notification);
    service.startForeground(notificationID, notification);
}

IntendService

服务中耗时的部分最好在子线程中处理

 onHandleIntent()就是在子线程中运行了,可以处理一些耗时操作。并且在服务运行结束后可以自动停止,onDestroy会被调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值