AIDL 应用间简单通信demo及基本问题

news2024/10/7 12:08:21

AIDL:Android Interface Definition Language,即Android接口定义语言。

他的作用大家已经知道了,有些童鞋对于其中的使用细节可能会有一些理解误差,并且会造成一写异常或者通讯失败。

我们先看几个关键点再看代码,如果项目不符合这几点,肯定会造成通讯失败或异常:

        1、客户端、服务端的aidl文件必须包名一致,以下错误就是这个问题引起的,

java.lang.SecurityException: Binder invocation to an incorrect interface

       2、可以自定义类型

        但是aidl路径中的类型文件,比如main/aidl包下的一个类型文件com.demo.aidl.bean.TestBean.aidl,必须在main/java 包下创建一个同路径的文件,并且实现Parcelable接口,也就是com.demo.aidl.bean.TestBean.java。TestBean.aidl文件内只需要写两行代码

第一行跟普通java文件一样,文件路径,第二行相当于一个声明

package com.jiao.aidlservicedemo.bean;

parcelable TestBean;

 Java同路径文件内容则是跟平常写代码一样,

package com.jiao.aidlservicedemo.bean.TestBean;

import android.os.Parcelable;

public class TalkContent implements Parcelable {
...
}

3、 绑定服务:

        因为是不同项目,跨进程了,并且提供服务端Service(Sevice通讯核心组件)代码也不在用一项目中,所以要注意绑定服务的方式

Intent intent = new Intent();
intent.setComponent(new ComponentName("com.jiao.aidlservicedemo", "com.jiao.aidlservicedemo.TalksService")); 
intent.setAction("com.jiao.aidlservicedemo.TalksService.aidl");
bindService(intent, conn, BIND_AUTO_CREATE);

ComponentName 里面两个参数

        Param1:所要通讯的项目(Service端)包名,也就是applicationId,一般与AndroidManifest.xml 中最外层标签 <manifest package="com.jiao.aidlclientdemo">中的package的值相同,但是如果在module里面的build.gradle中 applicationId 的值与项目包名不一致,则使用applicationId。

        Param2:Service端的Service 组件的路径+文件名(无后缀)

Param3:setAction

这个是组件Service在清单文件AndroidManifest.xml中注册时的<action android:name=“”>,如:

 <service
            android:name=".TalksService"
            android:enabled="true"
            android:exported="true">

            <intent-filter>
                <action android:name="com.jiao.aidlservicedemo.TalksService.aidl" />
            </intent-filter>
        </service>
enabled、exported,两个属性要为true

4、Android 11 及以上系统 跨应用通讯

        想通讯需要让客户端知道手机上是否有服务端这项目,此时需要在客户端的清单文件中注册一下权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jiao.aidlclientdemo">
    <!--    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"-->
    <!--        tools:ignore="QueryAllPackagesPermission" />-->
    <queries>
        <package android:name="com.jiao.aidlservicedemo" />
    </queries>
<application>
...
</application>

两种方法 ,第一种获取手机中安装APP列表权限,第二种比较安全一点,只是用<queries>申请一下服务端这个项目的安装情况<queries> 中可以写多个包名,里面package 的值,是Service所在的包名或者applicationId。

Demo代码

        项目 结构图  (ITalkAidlInterface.aidl为aidl核心类,IServiceCallback.aidl回调接口,TalkContent.aidl数据模型)

        

 ITalkAidlInterface.aidl

// ITalkAidlInterface.aidl
package com.jiao.aidlservicedemo;

// Declare any non-default types here with import statements
import com.jiao.aidlservicedemo.bean.TalkContent;
import com.jiao.aidlservicedemo.IServiceCallback;

interface ITalkAidlInterface {
       /**
        *   接收消息
        */
        void leavingMessage(in TalkContent talk);

         /**
          *
          * 提供消息
          */
        void getAllTalks( IServiceCallback iServicecallBack);
}

        IServiceCallback.aidl

// IServiceCallback.aidl
package com.jiao.aidlservicedemo;

interface IServiceCallback {

    void taks(inout Map talks);
}

 TalkContent.aidl

// TalkContent.aidl
package com.jiao.aidlservicedemo.bean;

parcelable TalkContent;

以上是aidl代码,客户端服务端都一样,可以直接复制过去,aidl部分写完之后,需要 编译一下项目 Make Prokect,自动生成一些文件到build中,然后开始写业务代码。

 TalkContent

package com.jiao.aidlservicedemo.bean;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * @author: jiaojunfeng
 * @date: 1/10/23
 * @describe:
 */
public class TalkContent implements Parcelable {
    private String talkContent;
    private String id;
    private String name;

    public TalkContent(String talkContent, String id, String name) {
        this.talkContent = talkContent;
        this.id = id;
        this.name = name;
    }

    public String getTalkContent() {
        return talkContent;
    }

    public void setTalkContent(String talkContent) {
        this.talkContent = talkContent;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    protected TalkContent(Parcel in) {
        talkContent = in.readString();
        id = in.readString();
        name = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(talkContent);
        dest.writeString(id);
        dest.writeString(name);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<TalkContent> CREATOR = new Creator<TalkContent>() {
        @Override
        public TalkContent createFromParcel(Parcel in) {
            return new TalkContent(in);
        }

        @Override
        public TalkContent[] newArray(int size) {
            return new TalkContent[size];
        }
    };

    @Override
    public String toString() {
        return "TalkContent{" +
                "talkContent='" + talkContent + '\'' +
                ", id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

服务端主要代码(MainActivity中没业务代码,可以忽略)

TalksService.java

package com.jiao.aidlservicedemo;

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

import com.jiao.aidlservicedemo.bean.TalkContent;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import androidx.annotation.Nullable;

/**
 * @author: jiaojunfeng
 * @date: 1/10/23
 * @describe:
 */
public class TalksService extends Service {

    private BinderService iTalkAidlInterface;

    @Override
    public void onCreate() {
        super.onCreate();
        iTalkAidlInterface = new BinderService(this);
    }

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

    public static class BinderService extends ITalkAidlInterface.Stub {
        Context context;

        public BinderService(Context context) {
            this.context = context;
        }

        @Override
        public void leavingMessage(TalkContent talk) throws RemoteException {
            Log.i("TalksService",talk.toString());
//此处是我做了一个本地化持久保存, 可以用arraylist来代替测试          
  SharedPreferencesUtil.saveTalk(context, talk.getId(), talk);
        }



        @Override
        public void getAllTalks( IServiceCallback iServiceCallback  ) throws RemoteException {
//此处是我做了一个本地化持久保存, 可以用arraylist来代替测试
            Map<String, ?> map = SharedPreferencesUtil.getTalks(context);
            iServiceCallback.taks(map);

        }
    }
}

客户端代码 主要是MainActivity

MainActivity

package com.jiao.aidlclientdemo;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.google.gson.Gson;
import com.jiao.aidlservicedemo.IServiceCallback;
import com.jiao.aidlservicedemo.ITalkAidlInterface;
import com.jiao.aidlservicedemo.bean.TalkContent;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private LinearLayout llyControl;
    private TextView tvBind;
    private TextView tvAdd;
    private TextView tvGet;
    private EditText etEditContent;
    private ListView lvHistory;
    Intent intent;

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

    private ITalkAidlInterface iPersonManager;
    ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.d("MainActivity", "onServiceConnected: ");
            iPersonManager = ITalkAidlInterface.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d("MainActivity", "onServiceDisconnected  ");
            iPersonManager = null;
        }
    };
    ArrayList<TalkContent> arrayList = new ArrayList<>();
    Talksadapter talksadapter;

    private void initView() {
        llyControl = findViewById(R.id.lly_control);
        tvBind = findViewById(R.id.tv_bind);
        tvAdd = findViewById(R.id.tv_add);
        tvGet = findViewById(R.id.tv_get);
        etEditContent = findViewById(R.id.et_edit_content);
        lvHistory = findViewById(R.id.lv_history);
        talksadapter = new Talksadapter(this, arrayList);
        lvHistory.setAdapter(talksadapter);
        tvBind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //如果是两个project,则客户端需用隐式调用,setPackage、setAction等
//        Intent intent1 = new Intent(getApplicationContext(), MyAidlService.class);
//        bindService(intent1, mConnection, BIND_AUTO_CREATE);
                intent = new Intent();
                intent.setComponent(new ComponentName("com.jiao.aidlservicedemo", "com.jiao.aidlservicedemo.TalksService"));
//        intent.setPackage("com.jiao.aidlservicedemo");
                intent.setAction("com.jiao.aidlservicedemo.TalksService.aidl");
                boolean isBind = bindService(intent, conn, BIND_AUTO_CREATE);
                Log.d("MainActivity", "isBind= " + isBind);

            }
        });
        tvGet.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (iPersonManager != null) {
//
                    try {
                        iPersonManager.getAllTalks(new IServiceCallback.Stub() {
                            @Override
                            public void taks(Map talks) throws RemoteException {

                                HashMap<String, Set> talkContentHashMap = (HashMap<String, Set>) talks;
                                for (String str : talkContentHashMap.keySet()) {
                                    Set<String> talkContent = talkContentHashMap.get(str);
                                    if (talkContent != null) {
                                        for (String talkC : talkContent) {
                                            arrayList.add(new Gson().fromJson(talkC, TalkContent.class));
                                        }

                                    }
                                    talksadapter.notifyDataSetChanged();
                                }
                            }
                        });
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        tvAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    if (iPersonManager != null) {
                        iPersonManager.leavingMessage(new TalkContent("hallo", "001", "张三"));
                    } else {
                        Log.d("MainActivity", "tvAdd iPersonManager=null ");
                    }
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

Talksadapter

package com.jiao.aidlclientdemo;

import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.jiao.aidlservicedemo.bean.TalkContent;

import java.util.ArrayList;

/**
 * @author: jiaojunfeng
 * @date: 1/11/23
 * @describe:
 */
public class Talksadapter extends BaseAdapter {

    private Context context;
    private ArrayList<TalkContent> arrayList;

    public Talksadapter(Context context, ArrayList<TalkContent> arrayList) {
        this.context = context;
        this.arrayList = arrayList;
    }

    @Override
    public int getCount() {
        return arrayList.size();
    }

    @Override
    public Object getItem(int position) {
        return arrayList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        convertView = View.inflate(context, R.layout.adapter_talks_item, null);
        TextView tvContent = convertView.findViewById(R.id.tv_content);
        TextView tvName = convertView.findViewById(R.id.tv_name);
        Log.d("MainActivity", "arrayList.get(position)=" + arrayList.get(position));
        TalkContent talkContent = arrayList.get(position);
        try {
            if (talkContent != null) {
                String content = talkContent.getTalkContent();
                tvContent.setText(content);
                tvName.setText(talkContent.getName());
            }
        } catch (Exception e) {
        }

        return convertView;
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/lly_control"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/tv_bind"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:padding="10dp"
            android:text="绑定" />

        <TextView
            android:id="@+id/tv_add"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_marginLeft="5dp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:padding="10dp"
            android:text="添加数据" />

        <TextView
            android:id="@+id/tv_get"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_marginLeft="5dp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:padding="10dp"
            android:text="获取数据" />
    </LinearLayout>

    <EditText
        android:id="@+id/et_edit_content"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_alignParentBottom="true"
        android:hint="请输入对话内容" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/et_edit_content"
        android:layout_below="@+id/lly_control">

        <ListView
            android:id="@+id/lv_history"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>


</RelativeLayout>

adapter_talks_item.xml

<?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:orientation="vertical">
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:minHeight="50dp"
        android:paddingLeft="4dp"
        android:textColor="#000000"
        android:textSize="14sp" />
    <TextView
        android:id="@+id/tv_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:minHeight="50dp"
        android:paddingLeft="14dp"
        android:textColor="#000000"
        android:textSize="14sp" />
</LinearLayout>

服务端清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.jiao.aidlservicedemo">


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!--        // enabled 是否可以被系统实例化,-->
        <!--        // 默认为 true 因为父标签 也有 enable 属性,-->
        <!--        // 所以必须两个都为默认值 true 的情况下服务才会被激活,否则不会激活。-->
        <!--       -->
        <!--        // exported 是否支持其它应用调用当前组件。-->
        <!--        // 默认值:如果包含有intent-filter 默认值为true;-->
        <!--        // 没有intent-filter默认值为false。-->

        <!--            //该Service可以响应带有com.bard.gplearning.IMyAidlInterface这个action的Intent。-->
        <!--            //此处Intent的action必须写成“服务器端包名.aidl文件名”-->
        <service
            android:name=".TalksService"
            android:enabled="true"
            android:exported="true"
          >

            <intent-filter>
                <action android:name="com.jiao.aidlservicedemo.TalksService.aidl" />
            </intent-filter>
        </service>
    </application>

</manifest>

客户端清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jiao.aidlclientdemo">
    <!--    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"-->
    <!--        tools:ignore="QueryAllPackagesPermission" />-->
    <queries>
        <package android:name="com.jiao.aidlservicedemo" />
    </queries>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

代码 我用到了

implementation 'com.squareup.retrofit2:converter-gson:2.0.0'

文中若有缺失或不对的地方 欢迎指证,谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/169292.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ffmpeg编译android平台-(ubuntu+ndkr16b+ffmpeg3.4.12)

一、环境配置 1、下载NDK,NDK老版本 1.1、 ubuntu下载 wget https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip1.2、解压NDK unzip android-ndk-r16b-linux-x86_64.zip1.3、配置NDK环境变量 vim /etc/profile1.4、 在profile文件中添加如下内容…

String.prototype.matchAll called with a non-global RegExp argument

如上 matchAll这个API 与 正则的全局匹配是不一样的。他会将匹配到的所有字符串以迭代器的形式返回出来。 我们可以使用Array.from或者数据解构来获得匹配到的数组。 他与正则全局匹配的区别是当正则表达式包含()捕获组的时候&#xff0c;全局匹配无法获得子匹配组的数据。 …

【Datewhale一起吃瓜 Task1】周志华西瓜书第一章+第二章

这里写目录标题机器学习是干什么的机器学习的理论基础: PAC模型基本术语关于数据关于假设关于模型训练机器学习任务分类归纳偏好模型的评估和选择训练流程划分数据集的方法留出法交叉验证自助法性能度量机器学习是干什么的 我们目前处于大数据时代&#xff0c;每天会产生数以亿…

一个监控系统的典型架构是什么样的

典型架构 采集器是负责采集监控数据的,采集到数据之后传输给服务端,通常是直接写入时序库。然后就是对时序库的数据进行分析和可视化,分析部分最典型的就是告警规则判断(复杂一些的会引入统计算法和机器学习的能力做预判),即图上的告警引擎,告警引擎产生告警事件之后交给…

华为MPLS跨域带RR实验配置

目录 Option B方案实验配置 配置建立Vpnv4邻居 配置反射器 配置RR和ASBR取消RT值检测 配置ASBR相连接口开启MPLS 配置ASBR向RR发送路由时更改下一跳 Option C1方案实验配置 Option C2方案实验配置 接口IP地址、底层IGP路由协议&#xff08;ISIS&#xff09;、MPLS LDP协…

一种环状二肽3705-26-8,cyclo(Pro-Phe),环(PHE-PRO)环状二肽

基础产品数据&#xff08;Basic Product Data&#xff09;&#xff1a;CAS号&#xff1a;3705-26-8中文名&#xff1a;环(PHE-PRO)英文名&#xff1a;cyclo(Pro-Phe)&#xff0c;CYCLO(-PHE-PRO)结构式&#xff08;Structural&#xff09;&#xff1a;详细产品数据&#xff08;…

qq消息撤回

开发工具 工具名称工具类型说明AndroidStuduo编辑工具开发工具jadxjava工具将apk解成java项目xposed插件工具插件qq版本8.8.80 开始 先通过jadx把apk反编译出来源码&#xff0c;通过build出来&#xff0c;在android studio打开&#xff0c;方便分析。 要撤回自己的消息&…

TMC步进电机驱动stealthChop

一直觉得tmc系列的芯片功能很强大&#xff0c;但是我自己读寄存器手册的感觉就是每个字我都认识&#xff0c;怎么就这么难懂。。。。 stealthChop 是一种电压控制技术&#xff0c;基于电压斩波器的工作远离&#xff0c;可在低速中速范围内以最大扭矩实现绝对静音的步进电机控制…

【推荐】自用软件工具推荐 WIN

一、图片查看器 Honeyview 蜂蜜浏览器 免费的图像查看器 下载和功能说明 (bandisoft.com) 轻量而快速可以显示包括 GPS 信息在内的 JPEG 格式的 EXIF 信息对图像格式进行批量转换和调整大小支持显示 GIF 和 WebP 动图无需解压即可直接查看压缩包中的图像支持的格式 图像格式…

大厂整个项目的开发规范流程

第1节、大厂码农开发基础 内容 本章节给大家介绍在互联网做开发&#xff0c;基础环境、开发技术以及上线和监控都会用到哪些东西。一般互联网大厂像阿里、京东、腾讯等都会有公司自研的一些技术组件&#xff0c;比如&#xff1a;RPC、MQ、数据库路由等&#xff0c;但所有的这些…

API 网关的功能用途及实现方式

1. API 网关诞生背景 前言 API 经济生态链已经在全球范围覆盖&#xff0c; 绝大多数企业都已经走在数字化转型的道路上&#xff0c;API 成为企业连接业务的核心载体&#xff0c; 并产生巨大的盈利空间。快速增长的 API 规模以及调用量&#xff0c;使得企业 IT 在架构上、模式…

flume整合数据到kafka,sparkStreaming消费数据,并存储到hbase和redis中

目录 1、模拟数据生成 2、flume采集数据 1、node01配置flume的conf文件 2、node02开发flume的配置文件 3、node03开发flume的配置文件 4、开发flume启动停止脚本 5、node01执行以下命令创建kafka的topic 6、启动并查看kafka的数据 3、SparkStreaming消费kafka中的数…

第二章.线性回归以及非线性回归—LASSO算法

第二章.线性回归以及非线性回归 2.13 LASSO算法 1.前期导入&#xff1a; 通过构造一个一阶惩罚函数获得一个精炼的模型&#xff1b;通过最终确定一些指标(变量)的系数为零&#xff0c;解释力很强 岭回归估计系数等于0的机会微乎其微&#xff0c;造成筛选变量困难 擅长处理具有…

如何实现根据环境切换不同配置?

在企业开发中&#xff0c;系统的配置信息往往会分不同的环境&#xff0c;如开发环境、测试环境、生产环境。当我们使用nacos做为配置中心时&#xff0c;一定会遇到的问题就是在应用中配置nacos的server-addr时测试环境的nacos地址和线上nacos地址如何区分的问题 拿开发环境和正…

4.4 可迭代对象(Iterable)与迭代器(Iterator)

4.4 可迭代对象(Iterable)与迭代器&#xff08;Iterator&#xff09; 4.4.1 可迭代&#xff08;Iterable&#xff09;对象 如果一个对象实现了__iter__方法&#xff0c;那么这个对象就是可迭代&#xff08;Iterable&#xff09;对象>>> #如何知道一个对象实现了那些…

STM32MP157内核移植相关bug

STM32MP157 官方Linux5.15内核移植相关bug一、主频问题二、驱动开发时的头文件缺失问题三、结语一、主频问题 在初学STM32MP157驱动开发时&#xff0c;笔者曾对官方最新版的Linux内核进行了移植&#xff0c;但是因为一些问题&#xff0c;导致移植后的系统存在一些bug。最近笔者…

Java学习之抽象类

目录 一、抽象类引出 二、抽象类的介绍 三、抽象类的细节 第一条 第二点 第三点 第四点 第五点 第六点 第七点 第八点 四、练习 第一题 第二题 一、抽象类引出 当父类的一些方法不能确定时,可以用abstract关键字来修饰该方法&#xff0c;这个方法就是抽象方法,用…

【设计模式】创建者模式·建造者模式

学习汇总入口【23种设计模式】学习汇总(数万字讲解体系思维导图) 写作不易&#xff0c;如果您觉得写的不错&#xff0c;欢迎给博主来一波点赞、收藏~让博主更有动力吧&#xff01; 一.概述 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 …

Python实现哈里斯鹰优化算法(HHO)优化支持向量机回归模型(SVR算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 2019年Heidari等人提出哈里斯鹰优化算法(Harris Hawk Optimization, HHO)&#xff0c;该算法有较强的全…

目标检测——day66 Scaled-YOLOv4: Scaling Cross Stage Partial Network

Scaled-Yolov4:可伸缩跨级部分网络 Scaled-YOLOv41. Introduction2. Related work2.1. Real-time object detection2.2. Model scaling&#xff08;模型缩放&#xff09;3. Principles of model scaling4. Scaled-YOLOv44.1. CSP-ized YOLOv44.2. YOLOv4-tiny4.3. YOLOv4-large…