飞道的博客

Android:Service生命周期方法与Service启动方式bindService与StartService

527人阅读  评论(0)

Service是什么

服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。不过需要注意的是,服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行 -————取自《第一行代码——Android》

Service生命周期

自调用的方法:

方法 作用
onCreate 创建服务
onStartCommond 开始服务
onDestroy 销毁服务
onBind 绑定服务
onunBind 解绑服务

手动调用方法

方法 作用
startService 启动服务
stopService 关闭服务
bindService 绑定服务
unBindService 解绑服务


此图展示了startService和bindservice两种启动service的方式的流程

StartService与BindService开启服务区别

服务身为android四大组件之一,它不能自己运行,他需要通过Context.startService或者Context.bindService来开启,

方式 区别
StartService 通过这种方式开启服务,调用者和服务本身没有关联,调用者退出了服务依然运行在后台,没有关联意味着调用者无法再操作这个服务,只能通过stopService或者stopSelf来停止服务
bindService 通过这种方式把service与调用者绑定在一起,通过这种方式调用者可以操作控制Service,但是调用者退出后Service同样会退出。

startService演示生命周期

startService开启服务后,如果服务未创建,则调用onCreate先创建服务,然后调用onStartCommond开始服务,并且服务启动后一直保持运行状态,除非触发stopService或stopSelf方法每个服务只会存在一个实例,所以运行多次startService也只会存在一个服务实例,并且只需要一次stopService就能结束。
下面演示一次完整的开启结束服务流程

布局添加两个按钮用于开启和结束服务,代码省略
Service代码,创建一个Service,每个生命周期方法打印一条日志

public class MyService extends Service {
    private String TAG = "Service";
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind: run" );
        return null;
    }

    @Override
    public void onCreate() {
        Log.e(TAG, "onCreate: run");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand: run" );
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy: run" );
        super.onDestroy();
    }
}

Activity中通过按钮开启结束Service

public class MainActivity extends AppCompatActivity {
    private Intent serviceOne;
    private Button stopBtn;
    private Button startBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        stopBtn = (Button)findViewById(R.id.stop_btn);
        startBtn = (Button)findViewById(R.id.start_btn);
        serviceOne = new Intent(this, MyService.class);
        
        stopBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(serviceOne);
            }
        });
        startBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startService(serviceOne);
            }
        });
    }
}

运行程序,查看日志,先点击开启再点击结束

点击多次开始再点击结束

由此可以验证以上观点,多次startService不会创建多个实例,同一时间只会存在一个该Service实例。
下面再来看看bindService开启服务

bindService开启可操作的服务

bindService与调用者也就是调用的Activity相绑定,bindService可以通过Service的onBind返回的Binder对象调用Binder对象的方法。
一个简短的bindService演示案例
首先添加两个按钮用于bindService与unbindService;
然后修改Myservice.class

public class MyService extends Service {
    private String TAG = "Service";
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind: run" );
        return new MyBind();
    }

    @Override
    public void onCreate() {
        Log.e(TAG, "onCreate: run");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand: run" );
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy: run" );
        super.onDestroy();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "onUnbind: run" );
        return super.onUnbind(intent);
    }

    class MyBind extends Binder {

        public MyService getService(){
            return MyService.this;
        }

        public void showLog(){
            Log.e(TAG, "showLog:This is MyBind " );
        }
    }
}

以上代码我们可以看到,我们仅仅修改了onBind的返回值,返回了一个MyBinder对象,以及增加了一个继承Binder的MyBinder内部类,类中很随意的写了两个方法,用于后期给调用者使用。
然后创建一个马上会用到的MyConnection类实现ServiceConnection接口

public class MyConnection implements ServiceConnection {

    public String TAG = "MyConnection";

    /**
     * 当我们的MyService的onBind返回值不是null的时候会运行这个方法
     * @param name
     * @param service
     */
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.e(TAG, "onServiceConnected: run");
        MyService.MyBind myBind = (MyService.MyBind) service;
        MyService service1 = myBind.getService();
        myBind.showLog();
    }

    /**
     * 当服务出现异常退出的时候会运行这个方法
     * @param name
     */

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.e(TAG, "onServiceDisconnected: run" );
    }
}

此类将用于bindService方法的第二个参数,这个参数不可或缺,重写改接口的两个回调方法,onServiceConnected方法可用于接收传递service传递的binder对象。
然后在调用者MainActivity中修改代码;

        myConnection = new MyConnection();
		bindBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //第一个参数是intent,用于指定Service
                //第二个参数是一个ServiceConnection接口,用于接收服务开启与结束的信息
                //第三个参数是开启服务的操作,用于BIND_AUTO_CREATE表示自动创建Service
                bindService(serviceOne,myConnection,BIND_AUTO_CREATE);
            }
        });
        unBindBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //关闭服务只需要传入ServiceConnection的实例就好
                unbindService(myConnection);
            }
        });

以上仅有添加的新代码,在两个按钮点击事件中添加绑定解绑操作。bindService中传入了我们的MyConnection实例,unbind结束服务也通过这个实例来结束。下面我们来看看运行状态

点击bindService:
点击bind后,先create,然后onBind(这时候就没有onstartCommond什么事了),返回binder对象后立刻跳转到MyConnection的onServiceConnected回调方法中,在这个回调函数中获取了Binder对象并且运行了其中的showLog方法。这就实现了创建到获取binder的过程。
点击unbindService:

点击解绑后就是onunBind解绑,然后onDestroy销毁服务。
值得注意的是多次重复运行bindService同样不会多次创建service,甚至不会多次绑定,可以看看一下多次点击bind按钮的输出结果:

可以看到主要回调方法都只运行了一次。

END

以上就是Service的生命周期方法以及两种主要开启service 的方式,当然还有更牛逼的开启方式,下一篇讲。


转载:https://blog.csdn.net/qq_28837549/article/details/106097477
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场