Android:安卓学习笔记之Service 的简单理解和使用

Posted JMW1407

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android:安卓学习笔记之Service 的简单理解和使用相关的知识,希望对你有一定的参考价值。

Service

1、简介

1.1、背景

你一般在什么情况下会使用Service?

经验总结:

  • Service其实就是背地搞事情,又不想让别人知道,举一个生活当中的例子,你想知道一件事情不需要直接去问,你可以通过侧面了解。这就是Service设计的初衷

Service为什么被设计出来?

  • 根据Service的定义,我们可以知道需要长期在后台进行的工作我们需要将其放在Service中去做。
  • 说得再通熟易懂一点,就是不能放在Activity中来执行的工作就必须得放到Service中去做。如:音乐播放、下载、上传大文件、定时关闭应用等功能。
  • 这些功能如果放到Activity中做的话,那Activity退出被销毁了的话,那这些功能也就停止了,这显然是不符合我们的设计要求的,所以要将他们放在Service中去执行。

1.2、什么是Service?

Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件。服务可由其他应用组件启动(如Activity),服务一旦被启动将在后台一直运行,即使启动服务的组件(Activity)已销毁也不受影响。

  • Service通常总是称之为“后台服务”.

此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。

其中“后台”一词是相对于前台而言的,具体是指其本身的运行并不依赖于用户可视的UI界面,因此,从实际业务需求上来理解,Service的适用场景应该具备以下条件:

  • 1.并不依赖于用户可视的UI界面(当然,这一条其实也不是绝对的,如前台Service就是与Notification界面结合使用的);
  • 2.具有较长时间的运行特性。

2、生命周期



2.1、常用函数

2.2、生命周期方法具体介绍


常见的生命周期使用

说明

3、分类


4、使用

4.1、本地Service

使用步骤

步骤1:新建子类继承Service类

需重写父类的onCreate()、onStartCommand()、onDestroy()和onBind()

MyService.java

public class MyService extends Service 


//启动Service之后,就可以在onCreate()或onStartCommand()方法里去执行一些具体的逻辑
//由于这里作Demo用,所以只打印一些语句
    @Override
    public void onCreate() 
        super.onCreate();
        System.out.println("执行了onCreat()");
    

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
        System.out.println("执行了onStartCommand()");
        return super.onStartCommand(intent, flags, startId);


    

    @Override
    public void onDestroy() 
        super.onDestroy();
        System.out.println("执行了onDestory()");
    

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

步骤2:在主布局文件设置两个Button分别用于启动和停止Service

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="scut.carson_ho.demo_service.MainActivity">

    <Button
        android:layout_centerInParent="true"
        android:id="@+id/startService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="启动服务" />

    <Button
        android:layout_centerInParent="true"
        android:layout_below="@+id/startService"
        android:id="@+id/stopService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="停止服务" />
</RelativeLayout>

步骤3:构建Intent对象,并调用startService()启动Service、stopService停止服务

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener 

    private Button startService;
    private Button stopService;

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

        startService = (Button) findViewById(R.id.startService);
        stopService = (Button) findViewById(R.id.stopService);

        startService.setOnClickListener(this);
        startService.setOnClickListener(this);
    

    @Override
    public void onClick(View v) 
        switch (v.getId()) 

            //点击启动Service Button
            case R.id.startService:
                //构建启动服务的Intent对象
                Intent startIntent = new Intent(this, MyService.class);
                //调用startService()方法-传入Intent对象,以此启动服务
                startService(startIntent);
                
            //点击停止Service Button
            case R.id.stopService:
                //构建停止服务的Intent对象
                Intent stopIntent = new Intent(this, MyService.class);
                //调用stopService()方法-传入Intent对象,以此停止服务
                stopService(stopIntent);
                
        
    

步骤4:在AndroidManifest.xml里注册Service

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="scut.carson_ho.demo_service">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

        </activity>

        //注册Service服务
        <service android:name=".MyService">
        </service>

    </application>

</manifest>

4.2、可通信的服务Service

上面介绍的Service是最基础的,但只能单机使用,即无法与Activity通信
接下来将在上面的基础用法上,增设“与Activity通信”的功能,

即使用绑定Service服务(Binder类、bindService()、onBind()、unbindService()、onUnbind())

步骤1:在新建子类继承Service类,并新建一个子类继承自Binder类、写入与Activity关联需要的方法、创建实例

public class MyService extends Service 

    private MyBinder mBinder = new MyBinder();

    @Override
    public void onCreate() 
        super.onCreate();
        System.out.println("执行了onCreat()");
    

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
        System.out.println("执行了onStartCommand()");
        return super.onStartCommand(intent, flags, startId);


    

    @Override
    public void onDestroy() 
        super.onDestroy();
        System.out.println("执行了onDestory()");
    

    @Nullable
    @Override
    public IBinder onBind(Intent intent) 
        System.out.println("执行了onBind()");
        //返回实例
        return mBinder;
    


    @Override
    public boolean onUnbind(Intent intent) 
        System.out.println("执行了onUnbind()");
        return super.onUnbind(intent);
    

    //新建一个子类继承自Binder类
    class MyBinder extends Binder 

        public void service_connect_Activity() 
            System.out.println("Service关联了Activity,并在Activity执行了Service的方法");

        
    

步骤2:在主布局文件再设置两个Button分别用于绑定和解绑Service

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="scut.carson_ho.demo_service.MainActivity">

    <Button
        android:layout_centerInParent="true"
        android:id="@+id/startService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="启动服务" />

    <Button
        android:layout_centerInParent="true"
        android:layout_below="@+id/startService"
        android:id="@+id/stopService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="停止服务" />

    <Button
        android:layout_centerInParent="true"
        android:layout_below="@id/stopService"
        android:id="@+id/bindService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="绑定服务" />

    <Button
        android:layout_centerInParent="true"
        android:layout_below="@id/bindService"
        android:id="@+id/unbindService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="解绑服务"
        />
</RelativeLayout>

步骤3:在Activity通过调用MyBinder类中的public方法来实现Activity与Service的联系

即实现了Activity指挥Service干什么Service就去干什么的功能

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener 

    private Button startService;
    private Button stopService;
    private Button bindService;
    private Button unbindService;

    private MyService.MyBinder myBinder;


    //创建ServiceConnection的匿名类
    private ServiceConnection connection = new ServiceConnection() 

        //重写onServiceConnected()方法和onServiceDisconnected()方法
        //在Activity与Service建立关联和解除关联的时候调用
        @Override
        public void onServiceDisconnected(ComponentName name) 
        

        //在Activity与Service解除关联的时候调用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) 
            //实例化Service的内部类myBinder
            //通过向下转型得到了MyBinder的实例
            myBinder = (MyService.MyBinder) service;
            //在Activity调用Service类的方法
            myBinder.service_connect_Activity();
        
    ;

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


        startService = (Button) findViewById(R.id.startService);
        stopService = (Button) findViewById(R.id.stopService);

        startService.setOnClickListener(this);
        stopService.setOnClickListener(this);

        bindService = (Button) findViewById(R.id.bindService);
        unbindService = (Button) findViewById(R.id.unbindService);

        bindService.setOnClickListener(this);
        unbindService.setOnClickListener(this);

    

    @Override
    public void onClick(View v) 
        switch (v.getId()) 

            //点击启动Service
            case R.id.startService:
                //构建启动服务的Intent对象
                Intent startIntent = new Intent(this, MyService.class);
                //调用startService()方法-传入Intent对象,以此启动服务
                startService(startIntent);
                break;

            //点击停止Service
            case R.id.stopService:
                //构建停止服务的Intent对象
                Intent stopIntent = new Intent(this, MyService.class);
                //调用stopService()方法-传入Intent对象,以此停止服务
                stopService(stopIntent);
                break;

            //点击绑定Service
            case R.id.bindService:
                //构建绑定服务的Intent对象
                Intent bindIntent = new Intent(this, MyService.class);
                //调用bindService()方法,以此停止服务

                bindService(bindIntent,connection,BIND_AUTO_CREATE);
                //参数说明
                //第一个参数:Intent对象
                //第二个参数:上面创建的Serviceconnection实例
                //第三个参数:标志位
                //这里传入BIND_AUTO_CREATE表示在Activity和Service建立关联后自动创建Service
                //这会使得MyService中的onCreate()方法得到执行,但onStartCommand()方法不会执行
                break;

            //点击解绑Service
            case R.id.unbindService:
                //调用unbindService()解绑服务
                //参数是上面创建的Serviceconnection实例
                unbindService(connection);
                break;

                default:
                    break;

        
    

4.3、前台Service

前台Service和后台Service(普通)最大的区别就在于:

前台Service在下拉通知栏有显示通知(如下图),但后台Service没有

前台Service优先级较高,不会由于系统内存不足而被回收;后台Service优先级较低,当系统出现内存不足情况时,很有可能会被回收

用法很简单,只需要在原有的Service类对onCreate()方法进行稍微修改即可,如下图:

@Override
    public void onCreate() 
        super.onCreate();
        System.out.println("执行了onCreat()");

        //添加下列代码将后台Service变成前台Service
        //构建"点击通知后打开MainActivity"的Intent对象
        Intent notificationIntent = new Intent(this,MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0);

        //新建Builer对象
        Notification.Builder builer = new Notification.Builder(this);
        builer.setContentTitle("前台服务通知的标题");//设置通知的标题
        builer.setContentText("前台服务通知的内容");//设置通知的内容
        builer.setSmallIcon(R.mipmap.ic_launcher);//设置通知的图标
        builer.setContentIntent(pendingIntent);//设置点击通知后的操作

        Notification notification = builer.getNotification();//将Builder对象转变成普通的notification
        startForeground(1, notification);//让Service变成前台Service,并在系统的状态栏显示出来

    

4.4、IntentService

4.4.1、Service和IntentService对比

Service 不是一个单独的进程,它和应用程序在同一个进程中,Service 也不是一个线程,它和线程没有任何关系,所以它不能直接处理耗时操作。

  • 如果直接把耗时操作放在 Service 的 onStartCommand() 中,很容易引起 ANR
    .如果有耗时操作就必须开启一个单独的线程来处理

IntentService

  • IntentService 是继承于 Service 并处理异步请求的一个类
  • 在 IntentService 内有一个工作线程来处理耗时操作,启动 IntentService 的方式和启动传统 Service 一样
  • 同时,当任务执行完后,IntentService 会自动停止,而不需要我们去手动控制。
  • 另外,可以启动 IntentService 多次,而每一个耗时操作会以工作队列的方式在IntentService 的onHandleIntent 回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

而且,所有请求都在一个单线程中,不会阻塞应用程序的主线程(UI Thread),同一时间只处理一个请求。

那么,用 IntentService 有什么好处呢?首先,我们省去了在 Service 中手动开线程的麻烦,第二,当操作完成时,我们不用手动停止 Service

4.4.2、使用

步骤1:定义 IntentService的子类

传入线程名称、复写onHandleIntent()方法

public class myIntentService extends IntentService 

  /** 
    * 在构造函数中传入线程名字
    **/  
    public myIntentService() 
        // 调用父类的构造函数
        // 参数 = 工作线程的名字
        super("myIntentService");
    

   /** 
     * 复写onHandleIntent()方法
     * 根据 Intent实现 耗时任务 操作
     **/  
    @Override
    protected void onHandleIntent(Intent intent) 

        // 根据 Intent的不同,进行不同的事务处理
        String taskName = intent.getExtras().getString("taskName");
        switch (taskName) 
            case "task1":
                Log.i("myIntentService", "do task1");
                break;
            case "task2":
                Log.i("myIntentService", "do task2");
                break;
            default:
                break;
        
    

    @Override
    public void onCreate() 
        Log.i("myIntentService", "onCreate");
        super.onCreate();
    
   /** 
     * 复写onStartCommand()方法
     * 默认实现 = 将请求的Intent添加到工作队列里
     **/  
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
        Log.i("myIntentService",以上是关于Android:安卓学习笔记之Service 的简单理解和使用的主要内容,如果未能解决你的问题,请参考以下文章

Android学习笔记之Service

安卓学习笔记1安卓基本组件Activity,Service,BoradCastReceiver,ContentProvider简介

安卓学习笔记

ANDROID_MARS学习笔记_S01原始版_018_SERVICE之Parcel

Android :安卓第一行代码学习笔记之 解析JSON格式数据

Android :安卓学习笔记之事件内存泄露 的简单理解