绑定服务service

什么是服务呢?

长期于后台运行的程序,如果是官方一点,首先它是一个组件,用于执行长期运行的任务,并且与用户没有交互。

通过Context.startService()来开启服务,通过Context.stop()来停止服务,还可以通过绑定来开启服务。

为什么要使用服务呢?

我们知道这个服务是用于执行长期后台运行的操作。有些时候,我们没有界面,但是程序仍然需要工作。比如说,我们播放音乐,在后台播放音乐。比如说,我们下载任务,在后台下载文件。这些都是没有界面 的后台运行程序,这些都是用服务做的。所以,服务就有它的用处了。

第二个原因是什么呢?

1、前台进程:可以理解为是最顶部的,直接跟用户交互的。比如说我们操作的Activity界面.

2、可见进程:可以见的,但是不操作的,比如说我们在一个Activity的顶部弹出一个Dialog,这个Dialog就是前台进程,但是这个Activity则是可见进程。

3、服务进程:服务可以理解为是忙碌的后台进程,虽然是在后台,但是它很忙碌。

4、后台进程:后台进程就是退隐到后台,不做事的进程。

5、空进程:空进程是不做事的,没有任何东西在上面跑着,仅作缓存作用。

假设,内存不够用了,会先杀谁呢?

首先杀的是空进程,要是还不够就杀后台进程,要是还不够,那么就杀服务,但是服务被杀死以后,等内存够用了,服务又会跑起来了。

所以:如果我们需要长期后台操作的任务,使用Service就对了!其实Framework里多数是服务。如果我们进行音乐播放,即使退到了后台,也可以播放,我们使用服务完成吧!如果我们下载东西,退到后台也能下载,那么我们就使用服务吧!如果我们在不停地记录日志,那我们就用服务吧!

如果面试问到:服务用于执行耗时操作,这是对的吗?

如时服务直接执行耗时操作,也会出现anr.

在这里给大家补充一下anr的时长知识。首先ANR的意思是android no response,也就是无相应或者理解为操作超时。

在android系统中广播的ANR时长为:

 // How long we allow a receiver to run before giving up on it.  
    static final int BROADCAST_FG_TIMEOUT = 10*1000;  
    static final int BROADCAST_BG_TIMEOUT = 60*1000;  

前台广播为10秒,后台广播为60秒。

按键操作的anr时长为:按钮事件的时长为5秒,常指的是Activity的操作。

// How long we wait until we timeout on key dispatching.  
static final int KEY_DISPATCHING_TIMEOUT = 5*1000;  

服务的话,前台服务为20秒超时,后台服务为200秒超时。

   // How long we wait for a service to finish executing.  
    static final int SERVICE_TIMEOUT = 20*1000;  
  
    // How long we wait for a service to finish executing.  
    static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10; 

如果在服务中直接做耗时操作,也是会出现ANR异常的。服务可以长期在后台运行,所以你可以这么做:如果要做耗时操作,比如说网络的访问,数据库的读写之类的,可以开线程去做。

服务的生命周期

我们在startService之后,就执行了onCreate方法,接着是onStartCommand方法。当我们执行stopService的时候,就会走onDestroy方法了。这就是服务最基本的生命周期了。其实onStart也是服务的生命周期,只是这个方法已经过时了。

绑定启动服务

1、开启服务

优点:服务长期运行

缺点:服务不能通讯

2、绑定服务

优点:可以通讯

缺点:不能长期运行

绑定服务步骤:

1、注册BindSrevice继承自Service类

重写onCreate、onBind、onUnbind、onDestroy方法

package org.crazyit.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

/**
 * 绑定本地服务
 */
public class BindService extends Service {
    private static final String TAG = "BindService";

    // 通过继承Binder,实现IBindService接口
    private class MyBinder extends Binder implements IBindService {
        @Override
        public void callServiceInnerMethod() {
            // 调用服务内部方法
            serviceInnerMethod();
        }
    }

    // Service被绑定时回调该方法
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind方法");
        // 返回MyBinder对象,绑定服务的地方通过接口调用方法
        return new MyBinder();
    }

    // Service被创建时回调该方法
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate方法");

    }

    // Service被断开连接时回调该方法
    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind方法");
        return true;
    }

    // Service被关闭之前回调该方法
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy方法");
    }

    private void serviceInnerMethod() {
        Log.d(TAG, "serviceInnerMethod: ");
    }
}

2、编写接口IBindService,绑定服务时,返回实现该接口和Binder类的类

package org.crazyit.service;


// 绑定服务要实现的接口
public interface IBindService {
    void callServiceInnerMethod();
}

并在该类的实现接口方法中调用服务的内部方法serviceInnerMethod(),由此可实现服务内部的方法被绑定服务处调用。

3、在Activity中绑定服务、解绑服务以及调用服务内部的方法

bindService()        参数1:intent意图        参数2:serviceConnection        参数3:Service.BIND_AUTO_CREATE自动绑定

在ServiceConnection的onServiceConnected()方法中接收绑定服务返回的IBinder,此处用继承Binder类实现IBindService的IBindService接口进行接收

通过该接口调用实现了接口的服务内部方法iBindService.callServiceInnerMethod();

package org.crazyit.service;

import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;

/**
 * bindService后,unBindService,服务不再运行
 * startService后,停止服务,服务仍在运行
 */
public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    private IBindService iBindService;

    // 定义一个ServiceConnection对象
    private ServiceConnection conn = new ServiceConnection() {
        // 当该Activity与Service连接成功时回调该方法
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected方法");
            // 获取Service的onBind方法所返回的MyBinder对象
            iBindService = (IBindService) service;
        }

        // 当该Activity与Service断开连接时回调该方法
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected方法");
            iBindService = null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 获取程序界面中的start、stop、getServiceStatus按钮
        Button bindBn = findViewById(R.id.bind);
        Button unbindBn = findViewById(R.id.unbind);
        Button getServiceInnerMethod = findViewById(R.id.getServiceStatus);
        // 创建启动Service的Intent
        Intent intent = new Intent(this, BindService.class);
        bindBn.setOnClickListener(view ->
                // 绑定指定Service
                bindService(intent, conn, Service.BIND_AUTO_CREATE));
        unbindBn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 解除绑定Service
                if (conn != null) {
                    unbindService(conn);
                }
            }
        });
        // 调用服务内部的方法
        getServiceInnerMethod.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                iBindService.callServiceInnerMethod();
            }
        });
    }
}

布局文件:

<?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:gravity="center_horizontal"
	android:orientation="vertical">

	<Button
		android:id="@+id/bind"
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:text="@string/bind"
		android:textSize="20sp" />

	<Button
		android:id="@+id/unbind"
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:text="@string/unbind"
		android:textSize="20sp" />

	<Button
		android:id="@+id/getServiceStatus"
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:text="@string/getServiceStatus"
		android:textSize="20sp" />
</LinearLayout>

总结:

绑定服务时生命周期:onCreate -> onBind

解绑服务时生命周期:onUnbind -> onDestroy

如果在服务内的onBind方法中返回null,那么在ServiceConnection的onServiceConnected方法不会调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值