(六)Android基础系列之:Service

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/androidzf/article/details/87860266

服务:Android系统的后台服务组件,在后台长时间运行并且不提供用户界面的应用程序组件

服务的特点:

  • 1.没有用户界面
  • 2.不会轻易被Android系统终止
  • 3.在系统资源恢复后Service也将自动恢复运行状态
  • 4.可用于进程间通信

一、启动式服务

销毁服务时函数的调用:onDestroy()

多次销毁服务,不会多次调用onDestroy(),但也不会报错.

启动式服务的特点:

  • A:一旦调用者启动了服务,则调用者和服务就没有直接关系了,即调用者退出了,服务照样在后台继续运行.
  • B:启动式服务无法将服务的执行结果返回给调用者,如Activity.
  • C:启动式服务无法调用服务中的公有方法
  • D:服务生命周期函数都运行在主线程中
1、启动服务

Intent service=new Intent(this,ServiceLifeCycler.class);
service.putExtra(“startMusic”,“启动音乐”);
service.putExtra(“pauseMusic”,“暂停音乐”);
service.putExtra(“resetMusic”,“重置音乐”);
service.putExtra(“stopMusic”,“停止音乐”);
//启动服务
this.startService(service);

2、停止服务(它杀)
 this.stopService(service);

自定义服务的编写步骤:

1.编写一个子类继承Service或者它的子类并重写抽象方法onBind(Intent intent)
public class ServiceLifeCycler extends Service {
    public IBinder onBind(Intent intent) {
            return null;
    }
}
2.由于服务是android四大组件(Activity,Content Provider,BroadcastReceiver,Service)之一,必须在功能清单文件中进行注册:
<service android:name=".service.ServiceLifeCycler"/>

服务的存在形式有两种:

  • A:启动式服务:一旦调用者启动了服务,那么即使调用者销毁了,对启动的服务没有影响.
  • B:绑定式服务:一旦调用者绑定了服务,那么在调用者销毁时服务也会一块销毁.

启动式服务的生命周期函数有:

	onCreate()====>onStartCommand()===>onStart()=====>onDestroy()

第一次启动服务时自动调用的生命函数有:

onCreate()===>onStartCommand()====>onStart();

第二次启动服务时自动调用的生命周期函数有

:onStartCommand()===>onStart();

结论:

  • onCreate()只有在第一次创建服务时才会自动调用的方法;
  • onStartCommand():每次启动服务都会自动调用的方法
  • onStart():每次启动服务都会自动调用的方法
    onDestroy():当服务被销毁时自动调用的方法,主要做资源释放工作等

用户停止服务时自动调用的方法为:onDestroy();多次停止服务不会多次执行onDestory()方法,但也不会报错.

服务的生命周期函数都运行在主线程中,因此如果想做耗时操作,则必须开启子线程来做;

调用者比如Activity如果采用startService(intent)启动了服务,则调用者比如activity无法调用服务中的公有方法,因为activity得不到服务对象.

二、IntentServce

IntentServce的特点:
  • 1.创建一个工作器线程用来执行所有的意图对象,意图对象传递给onStartCommand()方法.
  • 2.创建一个工作队列,每次只能通过一个意图对象,意图对象是通过onStartCommand()方法传递给工作队列的,把意图对象从工作
    队列中取出来以后会自动传递给onHandleIntent(Intent intent)的形参intent,做耗时操作,当前所有的意图对象都通过
    工作队列传递给onHandleIntent(Intent intent)的形参intent后,服务会自杀.
  • 3.提供了onBind()方法的默认实现,返回null;
IntentService的使用:
  • 1.编写一个类继承IntentService并提供无参构造函数,在无参构造函数中必须调用父类的带一个字符串参数的构造函数,这个字符串就是子线程的名称.
  • 2.必须重写父类的抽象方法onHandlerIntent(Intent intent)做耗时操作,当所有的意图对象都传递过来执行完毕后服务会自杀.
public class MyIntentService extends IntentService {
    public MyIntentService() {
        //参数childThread是子线程的名称
        super("childThread");
    }
    @Override
    public void onCreate() {
        super.onCreate();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }
    /**
     * 当从工作队列中取出意图对象后会传递给当前方法的形参intent,并做耗时操作,当前取出工作队列中所有的意图对象并处理完毕后会自杀.
     * @param intent 启动服务是使用的意图对象
     */
    @Override
    protected void onHandleIntent(Intent intent) {

        String name=intent.getStringExtra("name");
        String threadName=Thread.currentThread().getName();
        //模拟耗时操作
        SystemClock.sleep(3000);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

三、绑定服务

绑定式服务的编写和使用过程:

  • A:编写一个类继承Service或者它的子类
  • B:重写相关生命周期方法
onCreate()===>onBind()===>onUnbind()===>onRebind()===>onDestroy()
  • C:在功能清单文件中进行注册
<service android:name=".service.ServiceWithBindLifeCycler"></service>
  • D:在Activity中可以绑定服务和解绑服务
Intent service=new Intent(this,ServiceWithBindLifeCycler.class);

//绑定服务
this.bindService(
service, //意图对象并且指定了启动源和启动目标
connection,//服务连接对象
this.BIND_AUTO_CREATE//绑定选项,当前选项表示服务绑定即创建
);
//解绑服务
this.unbindService(connection);
绑定式服务的特点:
  • A:当用户第一次绑定服务时会自动调用onCreate()===>onBind()方法,多次绑定服务不会多次调用onCreate()和onBind()方法
  • B:如果解绑服务,则会自动调用
onUnbind()===>onDestroy();
  • C:多次解绑服务会报如下异常:
java.lang.IllegalStateException: Could not execute method of the activity。。。。
    Caused by: java.lang.IllegalArgumentException:
    Service not registered: com.example.servicewithbindcyclerdemo03.MainActivity$1@5351c19c
public class MainActivity extends AppCompatActivity {
    /**
     * 声明服务对象
     */
    private BoundServiceLifeCycler boundServiceLifeCycler;
    /**
     * 是否成功绑定服务的标志
     */
    private boolean isBindSuccess;
    /**
     * 声明并实例化服务连接对象
     */
    private ServiceConnection conn=new ServiceConnection() {
        /**
         * 当客户端成功绑定服务后自动调用的方法,如果绑定成功,则将绑定方法的返回值传递给形参service对象
         * @param name
         * @param service
         */
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //把父类的对象service强制转换成子类MyBinder类型的对象
            BoundServiceLifeCycler.MyBinder myBinder= (BoundServiceLifeCycler.MyBinder) service;
            boundServiceLifeCycler=myBinder.getService();

            //在调用者Activity中成功的调用了服务对象中的共有方法
            int randomNumber=boundServiceLifeCycler.getRandom();

            //绑定服务成功将标志位置为true
            isBindSuccess=true;
        }

        /**
         * 当服务意外断开连接时自动调用的方法
         * @param name
         */
        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBindSuccess=false;
        }
    };

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

    /**
     * 绑定服务
     * @param view
     */
    public void boundService(View view){
        Intent intent=new Intent(this, BoundServiceLifeCycler.class);
        //绑定服务需要三个参数:1.意图对象 2.服务连接对象,3.指定一个标志,绑定即自动创建服务
        this.bindService(
                intent,//意图对象
                conn, //服务连接对象
                Context.BIND_AUTO_CREATE//标志,绑定服务时如果服务还没有创建则自动创建服务
        );
    }

    /**
     * 解绑服务,
     * 多次解绑服务会报如下错误错:
     * java.lang.IllegalArgumentException:
     * Service not registered: com.hsj.example.boundservicedemo03.MainActivity$1@53530268
     *
     * @param view
     */
    public void unboundService(View view){
        if(this.isBindSuccess){
            //解绑服务,只需要传递一个参数:conn对象
            this.unbindService(conn);
            //成功解绑后还原标志位
            this.isBindSuccess=false;
        }else {
            Toast.makeText(this, "必须先绑定服务才能解绑!", Toast.LENGTH_SHORT).show();
        }

    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(this.isBindSuccess){
            //解绑服务,只需要传递一个参数:conn对象
            this.unbindService(conn);
            //成功解绑后还原标志位
            this.isBindSuccess=false;
        }
    }
}
public class BoundServiceLifeCycler extends Service {
    /**
     * 当服务第一次被创建时自动调用的方法
     */
    @Override
    public void onCreate() {
    }
    /**
     * 声明随机数对象
     */
    private Random random=new Random();
    /**
     * 返回0到10之间的随机数,包括0,不包括10,[0,10)
     * @return
     */
    public int getRandom(){
        int randomNumber= random.nextInt(10);
        return randomNumber;
    }
    /**
     * 当绑定服务时自动调用的方法,如果绑定成功则会将当前方法的返回值对象传递给
     * ServiceConnection类中的方法onServiceConnected(ComponentName name, IBinder service)
     * 的形参service
     *
     * @param intent
     * @return 如果返回值为null表示绑定失败,非null表示绑定成功
     */
    @Override
    public IBinder onBind(Intent intent) {
        MyBinder myBinder=new MyBinder();
       return  myBinder;
    }

    /**
     * 自定义Binder的子类MyBinder类
     */
    public class  MyBinder extends Binder{
        /**
         * 在内部类中访问外部类对象
         * @return 外部类对象
         */
        public BoundServiceLifeCycler getService(){
            return  BoundServiceLifeCycler.this;
        }
    }
    /**
     * 当解绑服务时自动调用的方法
     * @param intent
     * @return
     */
    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    /**
     * 当之前绑定过服务,并且onUnbind(Intent intent)方法的返回值为true,再次绑定时自动调用的方法
     * @param intent
     */
    @Override
    public void onRebind(Intent intent) {
    }
    /**
     * 当服务销毁时自动调用的方法
     */
    @Override
    public void onDestroy() {
    }
}

四、启动式服务和绑定式服务的混合使用

  • 1.第一次启动服务时生命周期函数的调用顺序为:onCreate()>onStartCommand()>onStart();

  • 2.接着绑定服务时生命周期函数的执行顺序为:onBind()====>onServiceConnected()(不是服务的生命周期函数);

  • 3.继续解绑服务时生命周期函数的调用顺序为:onUnbind(Intent intent);

  • 4.最后停止服务时函数的调用顺序为:onDestroy();

    1,2,3,2,3,4对应生命周期函数的调用顺序为:

onCreate()===>onStartCommand()===>onStart()=====>
onBind()===>onServiceConnected()=====>onUnbind()=====>onServiceConnected()====>onRebind()(如果想调用onRebind()方法必须在之前解绑服务时调用onUnbind()方法时返回值为true,否则不会调用onRebind()方法)====>onUnbind()=====>onDestroy().

1,2,4,3对应的生命周期函数的调用顺序为:

onCreate()===>onStartCommand()===>onStart()====>
onBind()====>onServiceConnected()====>
停止服务不会调用onDestroy()方法,因为服务还有一条绑定服务的关系引用地址onUnbind()====>onDestroy()

2,1,3,4对应的生命周期函数的调用顺序为:

onCreate()===>onBind()===>onServiceConnected()====>
onStartCommand()===>onStart()=====>
onUnbind()===>onDestroy().

2,1,4,3对应的生命周期函数的调用顺序为:

onCreate()===>onBind()===>onServiceConnected()====>
onStartCommand()===>onStart()=====>
停止服务不会调用onDestroy()方法,因为服务还有一条绑定服务的关系引用地址onUnbind()====>onDestroy().

结论:不管是启动式和还是绑定式服务,都会首先自动调用onCreate(),如果先启动服务,则会在调用onCreate()方法之后自动调用onStartCommand()==>onStart(),
如果先绑定服务,则会在调用完onCreate()方法之后自动调用onBind()方法,多次启动服务,
不会多次调用onCreate()方法,但会多次调用onStartCommand()和onStart()方法,多次绑定服务,
不会多次调用onCreate()和onBind()方法,多次停止服务不会多次调用onDestroy()方法,多次解绑服务会报错.

小技巧:

如果想绑定服务后,解绑服务不要让服务销毁,方便下次继续绑定同一个服务,可以先启动服务,之后在绑定服务,
在解绑服务时不会销毁服务,下次可以继续重新绑定上次启动好的服务.

猜你喜欢

转载自blog.csdn.net/androidzf/article/details/87860266