• Android四大组件之服务————服务的生命周期和启动方式


    ServiceAndroid四大组件之一,是一个计算型组件。它在Android开发中扮演着一个重要的角色,虽然他不如Activity那么常见,但是在很多App中都有着实际的应用场景。
    Service的运行不依赖于任何用户界面,所以它非常适合用于去执行那些不需要和用户交互但却需要长期运行的任务,如App的更新,音乐播放器等。
     
    服务有两种方式:
        开启服务,停止服务;
        绑定服务,解绑服务;
    如下是Service的生命周期:

     

    下面来体会下服务的方式吧;

     给主活动布局设置五个按钮,其中第三个是调用服务中的方法用的。(不能用new对象的方法调用service里的方法)

    然后再创建一个继承Service的FirstService类:

    其实根据生命周期来,生命周期的方法大致都用到了FirstService上,而我们解绑并未使用unbind方法

     

     然后用主活动调用服务:

    然后记得在AndroidManifest.xml里注册服务,四大组件都是需要在这里注册的;

     

     

     这样就可以测试开启活动和绑定活动的区别了。。。

    我们点击开启服务时,然后调用服务内部方法是不行的

     可以看出,绑定服务是可以调用服务内部的方法的

    不过这是总体,细节后面介绍。

    两个启动服务方式的不同:

      第一个不同:
              通过startSerive()直接启动服务:
              服务一旦开启,就与调用者没有任何关系,调用者的activity即使退出,也不会影响后台服务的运行。
     
              通过bindService()绑定服务:
              通过绑定方式开启的服务,服务跟调用者不求同生但求同死。如果调用者的activity退出了,那它绑定的服务也会跟着退出。
              注意:如果一个程序的activity绑定了服务,那么这个activity退出时,会报异常,说是服务没有被释放。
              那么我们可以重写activity的onDestory方法,方法内调用unbindService(),去显示的解除与服务的绑定。

      第二个不同点:
               Start直接启动服务的方法,调用者不能调用服务内部的方法。

               绑定服务启动服务的方法,调用者可以调用服务内部的方法;
               利用serviceConnection接口获取服务onbind返回的ibinder对象,
               这个对象同时实现了自定义的接口,这个接口内定义了服务中的方法。
     
     
    那详细讲解如何创建启动服务吧:
    主活动:
    package com.example.myservice;

    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;

    import androidx.appcompat.app.AppCompatActivity;

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = MainActivity.class.getName();
    private Button button;
    private Button button2;


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

    private void initView() {
    button = (Button) findViewById(R.id.button);
    button2 = (Button) findViewById(R.id.button2);
    button.setOnClickListener(this);
    button2.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
    switch (v.getId()) {
    case R.id.button:
    Intent intent = new Intent(this, FirstService.class);
    startService(intent);//开启
    break;
    case R.id.button2:
    Intent intent2 = new Intent(this, FirstService.class);
    stopService(intent2);//停止
    break;

    }
    }
    }

    主活动布局就是启动和暂停服务的两个按钮

    然后继承服务的类FirstService:
    package com.example.myservice;

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

    import androidx.annotation.Nullable;

    import java.util.logging.Logger;

    public class FirstService extends Service {
    private static final String TAG = FirstService.class.getName();


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

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

    // 被弃用了,
    @Override
    public void onStart(Intent intent, int startId) {
    Log.d(TAG, "onStart...");
    super.onStart(intent, startId);
    }

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

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

    这种就是简单的开启服务的方法;
    得记得AndroidManifest注册FirstService的服务
    开启后根据生命周期的提示给它走完输出。



    绑定服务的方法如下:
    主活动:
    package com.example.myservice;

    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;

    import androidx.appcompat.app.AppCompatActivity;

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = MainActivity.class.getName();
    private Button button3;
    private Button button4;
    private Button button5;
    private FirstService.InnerBinder removeBinf;

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

    private void initView() {
    button3 = (Button) findViewById(R.id.button3);
    button3.setOnClickListener(this);
    button4 = (Button) findViewById(R.id.button4);
    button4.setOnClickListener(this);
    button5 = (Button) findViewById(R.id.button5);
    button5.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
    switch (v.getId()) {
    case R.id.button3:
    Log.d(TAG, "调用服务内部方法。。。");
    removeBinf.callInnerMethod();
    break;
    case R.id.button4:
    Log.d(TAG, "绑定服务。。。");
    Intent intent4 = new Intent(this, FirstService.class);
    bindService(intent4, serviceConnection, BIND_AUTO_CREATE);//绑定
    break;
    case R.id.button5:
    Log.d(TAG, "解绑服务。。。");
    if (serviceConnection != null) {
    unbindService(serviceConnection);//解绑
    }
    break;
    }
    }

    private ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
    Log.d(TAG, "连接服务。。。");
    removeBinf = (FirstService.InnerBinder) service;

    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
    Log.d(TAG, "未连接服务。。。");
    removeBinf = null;
    }
    };
    }
    绑定需要三个固定参数,其中第二个是new一个服务连接类的对象和方法。
    第三个默认是自动创建,如果创建了就不创建(BIND_AUTO_CREATE

    然后FirstService类的方法就要使用Onbind()方法了
    package com.example.myservice;

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

    import androidx.annotation.Nullable;

    import java.util.logging.Logger;

    public class FirstService extends Service {
    private static final String TAG = FirstService.class.getName();

    public class InnerBinder extends Binder {
    public void callInnerMethod() {
    fun();
    }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
    Log.d(TAG, "绑定中...");

    return new InnerBinder();
    }

    private void fun() {
    Toast.makeText(this, "我是一个服务内部方法嘞", Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onCreate() {
    super.onCreate();
    Log.d(TAG, "onCreate...");
    }

    // 被弃用了,
    @Override
    public void onStart(Intent intent, int startId) {
    Log.d(TAG,"onStart...");
    super.onStart(intent, startId);
    }

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

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

    }
    先写内部类
    public class InnerBinder extends Binder {
    public void callInnerMethod() {
    fun();
    }
    }
    然后给onbind new一个内部类,在活动里的ServiceConnection里使用成员变量
        private FirstService.InnerBinder removeBinf;
      removeBinf = (FirstService.InnerBinder) service;
    强转成服务里的内部类方法实现绑定效果,然后绑定后用这个成员变量去调用服务里的方法,才可以实现活动调用服务内部方法。

    这种就是绑定服务的方法;
    得记得AndroidManifest注册FirstService的服务

     

    最后就成功调用了,服务的概念还是比较新奇,需要一段时间去理解接受。

    先了解一些概念性的东西可以更好的看懂和理解服务。



  • 相关阅读:
    /proc/interrupts 和 /proc/stat 查看中断的情况
    publish and submit
    camera shading比例
    高负载linux调优
    linux网络socket 接口转
    深入分析linux调度机制
    大型网站架构之分布式消息队列
    Linux下高并发socket最大连接数所受的各种限制(详解)
    Linux服务器高并发实践经历
    oracle: 分割字符串,或者查找字段里面的关键字(关键字1,关键字2,关键字3)
  • 原文地址:https://www.cnblogs.com/aolong/p/13434821.html
Copyright © 2020-2023  润新知