View体系之四大组件——Service详解

本文详细介绍了Android中的Service组件,包括启动状态与绑定状态的生命周期,onBind、onCreate、onStartCommand和onDestroy等关键方法。讨论了如何在Activity的生命周期中适当地绑定和解绑Service,以及在Service被停止和销毁时的处理。此外,还探讨了在后台运行Service时如何提高进程优先级以防止被系统回收,以及先启动Service与先绑定Service的不同情况。
摘要由CSDN通过智能技术生成
 View体系之四大组件——Service详解
        在学习Service之前,我们先提出以下几个问题:
        1、什么是Service?Service的作用是什么?
        2、Service有哪几种状态,其生命周期是什么?
        3、Service如何使用?(同一进程/跨进程)
        4、Service如何保活(进程保活)?
        5、对IntentService的理解
      好了,正题开始。
        
一、什么是Service?为什么Android会使用Service?
        Service顾明思义就是服务,是Andorid提供的实现后台运行的解决方案,主要用于执行后台任务。
        比如:通常我们在微信或者qq聊天时,电话进来,然后在打电话的过程中qq或者微信也会一直挂载,这就是Android的后台功能。 服务并不是运行在独立的进程中,而是会依赖创建服务时的应用程序进程,在这个应用程序进程被杀死后,依赖该进程的服务也会被杀死。
        又比如:我们在一个应用中一边下载视频,一边继续浏览其他内容。
        需要注意的是,服务(除IntentService外)并不会默认开启线程,服务的执行是在主线程中执行,因此如果在服务中执行耗时任务,也会导致主线程被阻塞,导致ANR,所以如果需要执行耗时任务,可以通过使用IntentService或者是开启线程来执行。

        
二、Service的状态和生命周期
    1、Service的状态
        根据Service是否与组件进行交互,可分为两种状态:启动状态和绑定状态。
  • 启动状态(不交互)
        使用范围:
        通常用于那些不需要交互、无限期后台运行的任务。比如从服务器下载数据
        
        如何使用:
        调用startService()启动,服务即可在后台无限期的运行,即使启动Service的组件已经销毁,也不影响Service的运行。
        需要停止Service时,可以通过组件调用stopService()方法或者在Service的子类中调用 stopself()方法即可。
       
  • 绑定状态
        使用范围:
        通常使用与那些需要与后台Service进行交互的情形

        如何使用:
        在绑定状态时,组件调用bindService()启动该Service,同时实现Service与组件的绑定。而绑定的服务中提供了一个IBinder()接口,用于组件和服务进行交互,发送请求,获取结果。
        而当所有的组件都与它解绑后,该Service才会被销毁。
        

     2、 Service的生命周期分析, 具体如下图 1:
图 1
            通过图片可以发现,启动状态和绑定状态的声明周期是不同的。
            需要注意,在绑定状态时,同一个组件对该Service多次绑定,只需要调用一次unbindService()即可解绑。即多次绑定一次解绑
           

三、Service的具体使用
        1、Manifest文件中声明
                  在AndroidManifest.xml中声明,如下:
<service
android:enabled=[ "true" | " false "]   //是否被系统实例化,默认为true
android:exported=[ "true" | " false "]    //是否可以被隐式调用
android:icon= "drawable resource"  
android:isolatedProcess=[ "true" | " false "]
android:label= "string resource"  
android:name= "string" //Service类名
android:permission= "string"  //权限
android:process= "string" > //是否在单独的进程中运行
. . . </service>

这里其他值采用默认,声明如下:
<service android:name=".activity.LocalService"/>
        2、继承Service类。具体如下:
package com.sky_wf.de moutils.activity;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;

/**
* @Date : 2018/2/24
* @Author : WF
* @Description :
*/
public class LocalService extends Service
{
    @Nullable
    @Override
    public IBinder onBind(Intent intent)//所有继承Service都必须实现onBind()方法
    {
        return null;
    }

    @Override
    public void onCreate()//Service创建时调用,只调用一次
    {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy()//Service销毁时调用
    {
        super.onDestroy();
    }

}
        
      四大组件包括Application其实根本上来说,都继承了Context。因此我们经常在组件中这样写:
public class LoginActivity extends Activity
{
private Context context;
@override
public void onCreate()
{
context = this;
}
}          
其实在这里,this代表的就是当前LoginActivty的一个实例,而Context则是Activity的父类,context = this。这本身就是一种向上转型。
这里也就可以理解,为什么很多方法或者组件实例化时参数需要Context,而我们传入一个this就可以。又或者我们自己实例化一个Context传入。

  Service本身就是一个抽象类,继承ContextWrapper,而ContextWrapper则是继承与Context, 在Service这个抽象类中有唯一的一个抽象方法onBind()。

  • onBind(Intent intent)
         onBind()方法是Service中唯一的一个抽象方法,因此继承Service类时必须实现这个类。通常用于进行通信,尤其是后面我们会讲到的跨进程通信。
  • onCreate()
        在首次创建Service时调用,当重复执行startService()或者bindService()时,onCreate()不再执行。
  • onStartCommand(Intent intent,int flags,int startId)
        当组件调用startService()启动服务时,则系统会调用此方法,如果是第一次调用startService()则会先调用onCreate()再调用onStartCommand(),重复启动服务,只会调用                                onStartCommand()。
         通常我们在onStartCommand中执行一些后台处理。
         这里我们需要特别注意的是其返回的int值,目前有三种START_STICKY,START_NOT_STICKY,START_REDELIVER_INTENT。
            START_STICKY
             当Service因内存不足而被系统kill掉后,一段时间后内存再次空闲时,系统将会尝试重新创建此Service,一旦创建成功后将回调onStartCommand方法,但其中的Intent将是null,除非有挂起的               Intent,如pendingintent。
            适用于不执行命令、但无限期运行并等待作业的媒体播放器或类似服务。
            START_NOT_STICKY    
              当Service因内存不足而被系统kill后,即使系统内存再次空闲时,系统也不会尝试重新创建此Service。除非程序中再次调用startService启动此Service,这是最安全的选项,可以避免在不必要时                以及应用能够轻松重启所有未完成的作业时运行服务。    
            START_REDELIVER_INTENT      
              当Service因内存不足而被系统kill后,则会重建服务,之后调用onStartCommand()。与START_STICKY不同的是,其中的传递的Intent将是非空,是最后一次调用startService中的intent。
              适用于主动执行应该立即恢复的作业(例如下载文件)的服务。
  • onDestory()当服务停止且要被销毁时,则会调用此方法。
        
        3、布局文件和Activity

            (1)布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <Button
        android:id="@+id/btn_start"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:text="启动服务"
        />
    <Button
        android:id="@+id/btn_stop"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:text="停止服务"
        />
</LinearLayout>
        (2)Activity
package com.sky_wf.demoutils.activity;

import android.content.Intent;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值