服务 一个长期运行在后台的用户组件 不依赖于Activity

只有当系统必须回收内存资源时 才会被销毁

首先是创建服务
image

当写好后 会自动在清单文件中注册

image

服务的生命周期和启动方式

先简单介绍一下 然后用两个小案例来日志打印验证

第一种启动方式 startService()

image
启动服务的组件和服务之间没有关联 组件销毁 服务依旧运行

验证下:
package com.example.service;

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

public class TestService extends Service {
    public TestService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("文雅", "创建服务 onCreate()执行");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("文雅", "开启服务 onStartCommand()执行");
        return super.onStartCommand(intent, flags, startId);

    }

	//此处为第一种启动方式
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("文雅", "关闭服务 onDestroy()执行");

    }
}
package com.example.service;

import android.content.Intent;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

public class ToServiceActivity extends AppCompatActivity {
    @Override
    protected void onStart() {
        super.onStart();
        setContentView(R.layout.activity_toservice);
        Button bt1 = findViewById(R.id.bt1);
        Button bt2 = findViewById(R.id.bt2);
        Intent testService = new Intent(this, TestService.class);

        bt1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startService(testService);
            }
        });

        bt2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(testService);
            }
        });
    }
}

第一次启动服务
image
关闭Activity 打开 服务直接启动
image
关闭服务
image


第二种启动方式 bindService()

image
组件绑定服务 解绑服务 服务即销毁 多个组件可绑定一个服务

             * 第一个参数 指定启动的Service
             * 第二个参数 调用者与Service之间的连接状态
             * 第三个参数 绑定服务时是否自动创建Service
            bindService(intent, myconn, BIND_AUTO_CREATE);
package com.example.service;

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

public class MyBindService extends Service {
    public MyBindService() {
    }

    class MyBinder extends Binder {
        public void callMethod() {
            method();
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("芳芳", "创建服务 执行onCreate()方法");
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("芳芳", "绑定服务 执行onBind()方法");
        return new MyBinder();

    }

    public void method() {
        Log.i("芳芳", "调用服务中的method()方法");
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i("芳芳", "解绑服务 执行onUnbind()方法");
        return super.onUnbind(intent);

    }
}
package com.example.service;

import android.annotation.SuppressLint;

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

import androidx.appcompat.app.AppCompatActivity;

public class BindServiceActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btt1, btt2, btt3;
    private Myconn myconn;
    private MyBindService.MyBinder myBinder;
// @SuppressLint("MissingInflatedId") 是一个 Android Lint 注解,用于告诉 Lint 工具忽略某个特定的警告
    @SuppressLint("MissingInflatedId")
    @Override
    protected void onStart() {
        super.onStart();
        setContentView(R.layout.activity_bindservice);
        btt1 = findViewById(R.id.btt1);
        btt2 = findViewById(R.id.btt2);
        btt3 = findViewById(R.id.btt3);

        btt1.setOnClickListener(this);
        btt2.setOnClickListener(this);
        btt3.setOnClickListener(this);


    }

    @Override
    public void onClick(View v) {
        //绑定服务
        if (v.getId() == R.id.btt1) {
            if (myconn == null) {
                myconn = new Myconn();
            }
            Intent intent = new Intent(this, MyBindService.class);
            /**
             * 第一个参数 指定启动的Service
             * 第二个参数 调用者与Service之间的连接状态
             * 第三个参数 绑定服务时是否自动创建Service
             */
            bindService(intent, myconn, BIND_AUTO_CREATE);
        }
        //调用服务中的方法
        if (v.getId() == R.id.btt2) {
            myBinder.callMethod();
        }
        //解绑服务
        if (v.getId() == R.id.btt3) {
            if (myconn != null) {
                unbindService(myconn);
                myconn = null;
            }

        }


    }

    //bindService第二个参数 实现连接服务
    private class Myconn implements ServiceConnection {

        // 成功绑定时 调用onServiceConnected()方法
        // 失去连接时 调用onServiceDisconnected()方法
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myBinder = (MyBindService.MyBinder) service;
            Log.i("芳芳", "服务成功绑定");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    }
}

不能直接调用方法 必须在成功绑定后才能调用
image
绑定服务
image
调用方法
image
解绑服务
image

关于直接调用methon()方法 AI给出答复:

类型安全:onServiceConnected 方法接收一个 IBinder 类型的参数。尽管您知道这个 IBinder 实际上是 MyBinder 的一个实例,但编译器并不知道这一点。因此,您需要通过强制类型转换来将其转换为 MyBinder 类型,然后才能调用 callMethod() 方法。

访问权限:method() 方法是 MyBindService 类的一个公共方法,但它不是 IBinder 接口的一部分。因此,没有 MyBinder 作为中介,您无法直接访问它。

设计模式:使用 Binder 类是 Android 服务绑定的一种常见设计模式。它允许您定义特定的方法来与服务交互,而不是直接访问服务的所有公共方法。这有助于封装和抽象,使代码更加清晰和可维护。

posted on 2024-06-18 09:39  蒸饺  阅读(32)  评论(0)    收藏  举报