Android在kts中简单使用AIDL

Android在kts中简单使用AIDL

AIDL相信做Android都有所了解,跨进程通信会经常使用,这里就不展开讲解原理跨进程通信的方式了,最近项目换成kts的方式,于是把aidl也换成了统一的方式,其中遇到了很多问题,这里记录一下,直接上代码.

1.在groovy创建aidl文件:

在Groovy中是可以直接创建aidl文件的

在这里插入图片描述

2.生成的aidl文件如下:

在这里插入图片描述

interface IMyService {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);int add(int a, int b);
}

3.创建一个服务端Service:

MyService

package com.example.aidltestdemo;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;import androidx.annotation.Nullable;/*** @author: njb* @date: 2025/3/20 17:47* @desc: 描述*/
public class MyService extends Service {private final IMyService.Stub mBinder = new IMyService.Stub() {@Overridepublic void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {}@Overridepublic int add(int a, int b) throws RemoteException {return a + b;}};@Nullable@Overridepublic IBinder onBind(Intent intent) {return mBinder;}
}

4.注册服务:

<serviceandroid:name=".MyService"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.example.aidltestdemo.IMyService" /></intent-filter>
</service>

在这里插入图片描述

5.客户端代码:

package com.example.aidltestdemo;import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;import com.google.android.material.snackbar.Snackbar;public class MainActivity extends AppCompatActivity {private IMyService mService;private TextView textView;private static final  String TAG = "AIDlDemo";private ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mService = IMyService.Stub.asInterface(service);try {int result = mService.add(10086, 10010);Log.d(TAG,"---获取到的数据为---: " + result);Snackbar.make(textView,"获取到的数据为: " + result,Snackbar.LENGTH_SHORT).show();} catch (RemoteException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {mService = null;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initService() {Intent intent = new Intent();intent.setAction("com.example.aidltestdemo.IMyService");intent.setPackage("com.example.aidltestdemo");bindService(intent, mConnection, Context.BIND_AUTO_CREATE);}private void initView() {textView = findViewById(R.id.textView);textView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {initService();}});}@Overrideprotected void onDestroy() {super.onDestroy();unbindService(mConnection);}
}

6.布局文件:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="aidl简单测试"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

7.在kts中使用aidl:

如果是使用kts的方式默认创建aidl文件时提示没有配置创建不了,这就和之前有很大的区别。

在这里插入图片描述

8.在build.gradle添加配置:

在这里插入图片描述

再次创建aidl发现按钮是可以点击的,配置是有效果的。

在这里插入图片描述

9.新创建后的aidl文件:

在这里插入图片描述

9.1 服务端代码如下:

package com.example.aidldemo.serverimport android.app.Service
import android.content.Intent
import android.os.IBinder
import android.os.RemoteException
import com.example.aidldemo.aidl.IMyTestServer/*** @author: njb* @date: 2025/3/19 23:24* @desc: 描述*/
class MyTestService : Service() {private val mBinder: IMyTestServer.Stub = object : IMyTestServer.Stub() {@Throws(RemoteException::class)override fun basicTypes(anInt: Int,aLong: Long,aBoolean: Boolean,aFloat: Float,aDouble: Double,aString: String) {}@Throws(RemoteException::class)override fun add(a: Int, b: Int): Int {return a + b}}override fun onBind(intent: Intent): IBinder? {return mBinder}
}

9.2 注册服务:

<service android:name=".server.MyTestService"android:process=":remote"android:enabled="true"android:exported="true">

9.3 客户端代码:

package com.example.aidldemo.aidlimport android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.example.aidldemo.R
import com.example.aidldemo.server.MyTestService
import com.google.android.material.snackbar.Snackbarclass MainActivity : AppCompatActivity(){private lateinit var mTvBind: TextViewprivate val TAG = MainActivity::class.java.nameprivate var testServer: IMyTestServer ?=nullprivate val mConnection: ServiceConnection = object : ServiceConnection {override fun onServiceConnected(name: ComponentName, service: IBinder) {testServer = IMyTestServer.Stub.asInterface(service)try {testServer?.let {val result: Int = it.add(188, 288)Log.d(TAG, "--结果为--: $result")Snackbar.make(mTvBind,"--获取到的数据为--: $result",Snackbar.LENGTH_SHORT).show()}} catch (rme: RemoteException) {rme.printStackTrace()}}override fun onServiceDisconnected(name: ComponentName) {try {testServer = null} catch (e: RemoteException) {e.printStackTrace()}}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)mTvBind = findViewById(R.id.tv_bind)mTvBind.setOnClickListener{val intent = Intent(this@MainActivity,MyTestService::class.java)bindService(intent, mConnection, BIND_AUTO_CREATE)}}override fun onDestroy() {super.onDestroy()if(testServer != null && testServer!!.asBinder().isBinderAlive){testServer = null}unbindService(mConnection)}}

10.新建一个Book服务:

// ICarManager.aidl
package com.example.aidldemo.aidl;
import com.example.aidldemo.aidl.Book;
import com.example.aidldemo.aidl.IOnNewBookAddListener;
// Declare any non-default types here with import statementsinterface IBookManager {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);List<Book> getBookList();void addNewBook(in Book book);void registerListener(IOnNewBookAddListener listener);void unregisterListener(IOnNewBookAddListener listener);
}

11.新增Book列表数据接口:

// IOnNewCarAddListener.aidl
package com.example.aidldemo.aidl;
import com.example.aidldemo.aidl.Book;
// Declare any non-default types here with import statementsinterface IOnNewBookAddListener {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);void onNewBookAdd(in Book newBook);
}

12.IBook接口:

interface IBook {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);
}

13.注册服务:

<service android:name=".server.BookManagerService"android:process=":remote"android:enabled="true"android:exported="true">
</service>

14.客户端Book测试代码:

package com.example.aidldemo.aidlimport android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatTextView
import com.example.aidldemo.R
import com.example.aidldemo.databinding.ActivityMainBinding
import com.example.aidldemo.server.BookManagerService/*** @author: njb* @date:   2025/3/22 19:27* @desc:   描述*/
class BookTestActivity :AppCompatActivity(){private val TAG: String = "TestActivity"private var bookManager: IBookManager? = nullprivate lateinit var binding:ActivityMainBindingprivate val mConnection: ServiceConnection = object : ServiceConnection {override fun onServiceConnected(name: ComponentName, service: IBinder) {bookManager = IBookManager.Stub.asInterface(service)try {bookManager?.let {val books = it.getBookList()if (books != null && books.isNotEmpty()) {Log.d(TAG, " -- onServiceConnected -- book:$books")}it.registerListener(clientListener)}} catch (e: RemoteException) {e.printStackTrace()}}override fun onServiceDisconnected(name: ComponentName) {try {bookManager?.unregisterListener(clientListener)} catch (e: RemoteException) {e.printStackTrace()}}}private val clientListener: IOnNewBookAddListener = object : IOnNewBookAddListener.Stub() {@Throws(RemoteException::class)override fun basicTypes(anInt: Int,aLong: Long,aBoolean: Boolean,aFloat: Float,aDouble: Double,aString: String) {}@Throws(RemoteException::class)override fun onNewBookAdd(newBook: Book) {Log.d(TAG, " -- onNewBookAdd -- newBook:$newBook")}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)binding.tvBind.setOnClickListener{val intent = Intent(this@BookTestActivity, BookManagerService::class.java)bindService(intent, mConnection, BIND_AUTO_CREATE)}binding.tvGet.setOnClickListener{try {val books = bookManager!!.bookListif (books != null && books.isNotEmpty()) {Log.d(TAG, " -- onClick -- books:$books")}} catch (e: Exception) {e.printStackTrace()}}binding.tvAdd.setOnClickListener{try {bookManager?.let {it.addNewBook(Book(1003, "计算机组成原理"))it.addNewBook(Book(1004, "操作系统"))}} catch (e: RemoteException) {e.printStackTrace()}}}override fun onDestroy() {super.onDestroy()if (bookManager != null && bookManager!!.asBinder().isBinderAlive) {try {bookManager?.unregisterListener(clientListener)} catch (e: RemoteException) {e.printStackTrace()}}unbindService(mConnection)}
}

15.普通实体类序列化:

package com.example.aidldemo.aidl;import android.os.Parcel;
import android.os.Parcelable;import androidx.annotation.NonNull;/*** @author: njb* @date: 2025/3/19 23:22* @desc: 描述*/
public class Book implements Parcelable {private int id;private String name;public Book(int id, String name){this.id = id;this.name = name;}protected Book(Parcel in) {id = in.readInt();name = in.readString();}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public static final Creator<Book> CREATOR = new Creator<Book>() {@Overridepublic Book createFromParcel(Parcel in) {return new Book(in);}@Overridepublic Book[] newArray(int size) {return new Book[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(id);dest.writeString(name);}@NonNull@Overridepublic String toString() {return String.format("[id:%d, name:%s]",id, name);}}

16.使用Parcelize序列化:

16.1 在app的build.gradle目录添加插件配置:

plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)id ("kotlin-parcelize")
}

在这里插入图片描述

16.2 实体类使用Parcelize方式:

和普通的方式对比发现代码简洁了很多,而且使用很方便,大大减少了开发人员的工作,当然我们要搞懂其原理才能达到事半功倍的效果,要不然只是会使用,而不知道为啥这么使用及使用他的优势和原理,对自身成长有限.

@Parcelize
data class Book(val id: Int,val name:String
):Parcelable

16.3 在libs.versions.toml添加如下插件:

jetbrains-kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }

16.4 在项目build.gradle添加配置:

plugins {alias(libs.plugins.android.application) apply falsealias(libs.plugins.jetbrains.kotlin.android) apply falsealias(libs.plugins.jetbrains.kotlin.parcelize) apply false
}

在这里插入图片描述

16.5 在app的build.gradle配置:

plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)alias(libs.plugins.jetbrains.kotlin.parcelize)
}

在这里插入图片描述

17.Parcelable的优势如下:

  • 高效性能:相比Serializable,Parcelable在序列化和反序列化过程中更加高效,因为它避免了反射的开销。
  • 跨进程传输:Parcelable适用于在不同进程之间传输数据,例如在Android中,我们可以将Parcelable对象传递给另一个应用程序组件。
  • 灵活性:Parcelable允许我们选择性地序列化对象的某些字段,而不是整个对象,这在某些情况下可以提高性能和减少传输的数据量。

18.遇到问题如下:

18.1 项目编译失败:

创建的Book服务和Book实例不在一个目录导致编译失败

在这里插入图片描述

在这里插入图片描述

18.2 把两个类放同一目录编译成功:

在这里插入图片描述

18.3 添加Parcelize插件依赖报错:

在这里插入图片描述

18.4 在build.gradle.kts添加以下配置:

plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)id ("kotlin-parcelize")
}

18.5 使用Version Catalog方式:

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
jetbrains-kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
plugins {alias(libs.plugins.android.application) apply falsealias(libs.plugins.jetbrains.kotlin.android) apply falsealias(libs.plugins.jetbrains.kotlin.parcelize) apply false
}
plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)alias(libs.plugins.jetbrains.kotlin.parcelize)
}

19.实现的效果如下:

在这里插入图片描述

在这里插入图片描述

20.日志打印如下:

o                 D  Installing profile for com.example.aidldemo
2025-03-23 20:26:39.912  4722-4722  TestActivity            com.example.aidldemo                 D   -- onServiceConnected -- book:[Book(id=1001, name=Java入门到精通)]
---------------------------- PROCESS STARTED (4797) for package com.example.aidldemo ----------------------------
2025-03-23 20:26:42.911  4722-4741  TestActivity            com.example.aidldemo                 D   -- onNewBookAdd -- newBook:Book(id=1002, name=C++程序设计)
2025-03-23 20:27:24.033  4722-4722  TestActivity            com.example.aidldemo                 D   -- onClick -- books:[Book(id=1001, name=Java入门到精通), Book(id=1002, name=C++程序设计)]
2025-03-23 20:27:39.776  4722-4722  TestActivity            com.example.aidldemo                 D   -- onNewBookAdd -- newBook:Book(id=1003, name=计算机组成原理)
2025-03-23 20:27:39.777  4722-4722  TestActivity            com.example.aidldemo                 D   -- onNewBookAdd -- newBook:Book(id=1004, name=操作系统)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

21.总结:

  • 使用kts的方式需要先使用buildFeatures配置aidl.
  • 使用Parcelize序列化数据很简单方便.
  • 要注意创建aidl文件的目录和包名这些在同一目录.
  • 使用Version Catalog方式要主要依赖配置的方式.
  • 感兴趣的小伙伴可以自己尝试一下,后面会讲解aidl如何传输大文件.

22.源码如下:

https://gitee.com/jackning_admin/aidl-test-demo

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习本地部署DeepSeek的过程(基于ollama)

DeepSeek除了支持在线调用服务接口外&#xff0c;还支持本地部署后调用本地服务&#xff0c;这样的好处是不需要api key&#xff0c;且资源独占&#xff0c;还能训练个人知识库。本文学习并记录本地部署DeepSeek的过程。   参考文献3中列出了不同模型对于电脑硬件的要求&…

文献分享: ColXTR——将ColBERTv2的优化引入ColXTR

1. ColXTR \textbf{1. ColXTR} 1. ColXTR原理 1.1. ColBERTv2 \textbf{1.1. ColBERTv2} 1.1. ColBERTv2概述 1.1.1. \textbf{1.1.1. } 1.1.1. 训练优化 1️⃣难负样本生成 初筛&#xff1a;基于 BM-25 \text{BM-25} BM-25找到可能的负样本重排&#xff1a;使用 KL \text{KL} KL…

Altium Designer数模电学习笔记

模电 电容 **退耦&#xff1a;**利用通交阻直&#xff0c;将看似直流的信号中的交流成分滤除 &#xff08;一般用在给MPU供电&#xff0c;尽量小一些&#xff0c;10nf~100nf~1uf以下&#xff09; **滤波&#xff1a;**也可以理解为给电容充电&#xff0c;让电容在电平为低时…

从指令集鸿沟到硬件抽象:AI 如何重塑手机与电脑编程语言差异——PanLang 原型全栈设计方案与实验性探索1

AI 如何跨越指令集鸿沟&#xff1f;手机与电脑编程语言差异溯源与统一路径——PanLang 原型全栈设计方案与实验性探索1 文章目录 AI 如何跨越指令集鸿沟&#xff1f;手机与电脑编程语言差异溯源与统一路径——PanLang 原型全栈设计方案与实验性探索1前言一、手机与电脑编程语言…

python 实现一个简单的window 任务管理器

import tkinter as tk from tkinter import ttk import psutil# 运行此代码前&#xff0c;请确保已经安装了 psutil 库&#xff0c;可以使用 pip install psutil 进行安装。 # 由于获取进程信息可能会受到权限限制&#xff0c;某些进程的信息可能无法获取&#xff0c;代码中已经…

C之(15)cppcheck使用介绍

C之(15)cppcheck使用介绍 Author: Once Day Date: 2025年3月23日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可查看专栏: Linux实践记录_Once_day的博客-CS…

Ant Design Vue Select 选择器 全选 功能

Vue.js的组件库Ant Design Vue Select 选择器没有全选功能&#xff0c;如下图所示&#xff1a; 在项目中&#xff0c;我们自己实现了全选和清空功能&#xff0c;如下所示&#xff1a; 代码如下所示&#xff1a; <!--* 参数配置 - 风力发电 - 曲线图 * 猴王软件学院 - 大强 …

CaiT (Class-Attention in Image Transformers):深度图像Transformer的创新之路

CaiT (Class-Attention in Image Transformers)&#xff1a;深度图像Transformer的创新之路 近年来&#xff0c;Transformers 模型在自然语言处理领域的成功逐渐扩展到了计算机视觉领域&#xff0c;尤其是图像分类任务中&#xff0c;Vision Transformer (ViT) 的提出打破了卷积…

Qt之MVC架构MVD

什么是MVC架构&#xff1a; MVC模式&#xff08;Model–view–controller&#xff09;是软件工程中的一种软件架构模式&#xff0c;把软件系统分为三个基本部分&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controll…

数组,指针 易混题解析(二)

目录 一.基础 1. 2. 二.中等 1. 坑 2. 3.指针1到底加什么 三.偏难 1.&#xff08;小端 x86&#xff09; 2.通过数组指针进行偏移的时候怎么偏移 3. 大BOSS &#xff08;1&#xff09;**cpp &#xff08;2&#xff09;*-- * cpp 3 &#xff08;3&#xff09;*c…

数据建模流程: 概念模型>>逻辑模型>>物理模型

数据建模流程 概念模型 概念模型是一种高层次的数据模型&#xff0c;用于描述系统中的关键业务概念及其之间的关系。它主要关注业务需求和数据需求&#xff0c;而不涉及具体的技术实现细节。概念模型通常用于在项目初期帮助业务人员和技术人员达成共识&#xff0c;确保对业务需…

spring-security原理与应用系列:建造者

目录 1.构建过程 AbstractSecurityBuilder AbstractConfiguredSecurityBuilder WebSecurity 2.建造者类图 SecurityBuilder ​​​​​​​AbstractSecurityBuilder ​​​​​​​AbstractConfiguredSecurityBuilder ​​​​​​​WebSecurity 3.小结 紧接上一篇文…

结合代码理解Spring AOP的概念(切面、切入点、连接点等)

前情回顾 对AOP的理解 我这篇文章介绍了为什么要有AOP&#xff08;AOP解决了什么问题&#xff09;以及如何实现AOP。但在实现AOP的时候&#xff0c;并未探讨AOP相关概念&#xff0c;例如&#xff1a;切面、切入点、连接点等。因此&#xff0c;本篇文章希望结合代码去理解Spring…

【AI大模型】搭建本地大模型GPT-NeoX:详细步骤及常见问题处理

搭建本地大模型GPT-NeoX:详细步骤及常见问题处理 GPT-NeoX是一个开源的大型语言模型框架,由EleutherAI开发,可用于训练和部署类似GPT-3的大型语言模型。本指南将详细介绍如何在本地环境中搭建GPT-NeoX,并解决过程中可能遇到的常见问题。 1. 系统要求 1.1 硬件要求 1.2 软…

Copilot提示词库用法:调整自己想要的,记住常用的,分享该共用的

不论你是 Microsoft 365 Copilot 的新用户还是熟练运用的老鸟&#xff0c;不论你是使用copilot chat&#xff0c;还是在office365中使用copilot&#xff0c;copilot提示词库都将帮助你充分使用copilot这一划时代的产品。它不仅可以帮助你记住日常工作中常用的prompt提示词&…

Spring:AOP

一、AOP概念的引入 为了更好地介绍AOP&#xff0c;我们以登录作为示例。 首先&#xff0c;我们先来看一下登录的原理&#xff1a; 如图所示&#xff0c;这是一个基本的登录原理图&#xff0c;但是如果我们想要在这个登录过程上再添加一些新的功能&#xff0c;比如权限校验&am…

Ubuntu实时读取音乐软件的音频流

文章目录 一. 前言二. 开发环境三. 具体操作四. 实际效果 一. 前言 起因是这样的&#xff0c;我需要在Ubuntu中&#xff0c;实时读取正在播放音乐的音频流&#xff0c;然后对音频进行相关的处理。本来打算使用的PipewireHelvum的方式实现&#xff0c;好处是可以直接利用Helvum…

CUDA 学习(4)——CUDA 编程模型

CPU 和 GPU 由于结构的不同&#xff0c;具有不同的特点&#xff1a; CPU&#xff1a;擅长流程控制和逻辑处理&#xff0c;不规则数据结构&#xff0c;不可预测存储结构&#xff0c;单线程程序&#xff0c;分支密集型算法GPU&#xff1a;擅长数据并行计算&#xff0c;规则数据结…

前端会话控制技术:cookie/session/token

目录 前端中的 Cookie、Session 和 Token&#xff1a;详解与应用1. Cookie1.1 什么是 Cookie&#xff1f;1.2 Cookie 的工作原理1.3 Cookie 的特点1.4 Cookie 的用途1.5 Cookie 的安全性 2. Session2.1 什么是 Session&#xff1f;2.2 Session 的工作原理2.3 Session 的特点2.4…

MATLAB实现基于“蚁群算法”的AMR路径规划

目录 1 问题描述 2 算法理论 3 求解步骤 4 运行结果 5 代码部分 1 问题描述 移动机器人路径规划是机器人学的一个重要研究领域。它要求机器人依据某个或某些优化原则 (如最小能量消耗&#xff0c;最短行走路线&#xff0c;最短行走时间等)&#xff0c;在其工作空间中找到一…