当前位置: 首页 > news >正文

Android RecyclerView 之 列表宫格布局的切换

前言

RecyclerView 的使用我就不再多说,接下来的几篇文章主要说一下 RecyclerView 的实用小功能,包括 列表宫格的切换,吸顶效果,多布局效果等,今天这篇文章就来实现一下列表宫格的切换,效果如下


一、数据来源

数据来源于知乎日报API,采用 okhttp+retrofit 组合方式请求获取,网络请求没有进行二次封装,只是简单请求数据源,对于有需求的用户自行进行封装修改。

二、使用步骤

1.引入库

  //万能适配器implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.50'//卡片布局implementation 'androidx.cardview:cardview:1.0.0'//图片加载implementation 'com.github.bumptech.glide:glide:4.9.0'//json解析implementation 'com.alibaba:fastjson:1.2.61'//标题栏implementation 'com.github.goweii:ActionBarEx:3.2.2'// 只引入ActionBarEximplementation 'com.github.goweii.ActionBarEx:actionbarex:3.2.2'// 引入ActionBarCommon/Search/Super,依赖于ActionBarEximplementation 'com.github.goweii.ActionBarEx:actionbarex-common:3.2.2'

2.获取数据

 使用如下 URL 进行数据请求:API 使用的 HTTP Method 均为 GET

https://news-at.zhihu.com/api/3/news/hot

响应实例:

{"recent": [{"news_id": 3748552,"thumbnail": "http://p3.zhimg.com/67/6a/676a8337efec71a100eea6130482091b.jpg","title": "长得漂亮能力出众性格单纯的姑娘为什么会没有男朋友?","url": "http://daily.zhihu.com/api/2/news/3748552"}]
}

根据实例生成实体类 NewsListBean 实现序列换接口 Serializable

public class NewsListBean implements Serializable {private String date;private List<Recent> recent;public String getDate() {return date;}public void setDate(String date) {this.date = date;}public List<Recent> getRecent() {return recent;}public void setRecent(List<Recent> recent) {this.recent = recent;}public static class Recent implements Serializable {private String news_id;private String thumbnail;private String title;private String url;public String getNews_id() {return news_id;}public void setNews_id(String news_id) {this.news_id = news_id;}public String getThumbnail() {return thumbnail;}public void setThumbnail(String thumbnail) {this.thumbnail = thumbnail;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}}
}

写一个 接口类用来管理 API ,可以单独放在一个文件夹下

public interface ApiUrl {@GET("/api/4/news/hot")Call<NewsListBean> getPic();}

3.主要代码

1 activity_main.xml

这里使用了三方库  ActionBarEx 实现了沉浸式标题栏,使用了系统的 ProgressBar 实现请求加载框

<?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"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><per.goweii.actionbarex.ActionBarExandroid:id="@+id/abc_main_return"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#14a4fb"app:ab_autoImmersion="false"app:ab_bottomLineColor="#f3f3f3"app:ab_bottomLineHeight="0dp"app:ab_statusBarColor="#00000000"app:ab_statusBarMode="dark"app:ab_statusBarVisible="true"app:ab_titleBarHeight="50dp"app:ab_titleBarLayout="@layout/top" /><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/zh_lv"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@+id/abc_main_return" /><ProgressBarandroid:id="@+id/progressbar"style="@style/Base.Widget.AppCompat.ProgressBar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:visibility="gone" />
</RelativeLayout>

2 zh_item_layout.xml

列表子布局 ,采用 CardView 卡片布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/zh_card_View"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="@dimen/dp_10"android:layout_marginTop="10dp"android:layout_marginRight="@dimen/dp_10"android:layout_marginBottom="@dimen/dp_10"app:cardBackgroundColor="#ffffff"app:cardCornerRadius="10dp"app:cardElevation="10dp"app:cardPreventCornerOverlap="true"app:cardUseCompatPadding="false"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="120dp"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/transparent"><ImageViewandroid:id="@+id/news_image"android:layout_width="70dp"android:layout_height="70dp"android:layout_centerVertical="true"android:layout_margin="10dp"android:elevation="2dp"android:scaleType="fitXY" /><TextViewandroid:id="@+id/news_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginStart="10dp"android:layout_marginTop="10dp"android:layout_marginEnd="10dp"android:layout_toEndOf="@id/news_image"android:ellipsize="end"android:maxEms="15"android:singleLine="true"android:textColor="@color/black"android:textSize="20sp" /></RelativeLayout></RelativeLayout></androidx.cardview.widget.CardView>

3 zh_grid__item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/zh_card_View"android:layout_width="match_parent"android:layout_height="180dp"android:layout_marginLeft="@dimen/dp_10"android:layout_marginTop="10dp"android:layout_marginRight="@dimen/dp_10"android:layout_marginBottom="@dimen/dp_10"app:cardBackgroundColor="#ffffff"app:cardCornerRadius="10dp"app:cardElevation="10dp"app:cardPreventCornerOverlap="true"app:cardUseCompatPadding="false"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/transparent"android:gravity="center"android:orientation="vertical"android:padding="@dimen/dp_10"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="3"><ImageViewandroid:id="@+id/news_image"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitXY" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:gravity="center"><TextViewandroid:id="@+id/news_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:ellipsize="end"android:maxEms="8"android:singleLine="true"android:textColor="@color/black"android:textSize="20sp" /></LinearLayout></LinearLayout></androidx.cardview.widget.CardView>

4 NewsListAdapter 适配器

public class NewsListAdapter extends BaseQuickAdapter<NewsListBean.Recent, BaseViewHolder> {public NewsListAdapter(int layoutResId, @Nullable List<NewsListBean.Recent> data) {super(layoutResId, data);}@Overrideprotected void convert(@NonNull BaseViewHolder helper, NewsListBean.Recent item) {helper.setText(R.id.news_title, item.getTitle());String img = item.getThumbnail();ImageView newsImage = helper.getView(R.id.news_image);Glide.with(mContext).asBitmap().load(img).diskCacheStrategy(DiskCacheStrategy.ALL).into(newsImage);helper.addOnClickListener(R.id.zh_card_View);}}

5 BaseActivity 基类

public abstract class BaseActivity extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {Window window = getWindow();// 5.0以上系统状态栏透明if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);window.setStatusBarColor(Color.TRANSPARENT);}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {// 全屏显示,隐藏状态栏和导航栏,拉出状态栏和导航栏显示一会儿后消失。window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE// | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION// | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION// | View.SYSTEM_UI_FLAG_FULLSCREEN| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);} else {// 全屏显示,隐藏状态栏window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);}}//预防软键盘挡住输入框getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);//禁止横屏setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);super.onCreate(savedInstanceState);}}

6 MainActivity 主要代码 

这里主要通过一个 boolean 值 isGrid 来判断是否切换状态来加载不同的布局,以及布局管理器来达到实际效果

public class MainActivity extends BaseActivity {private RecyclerView zhLv;private ProgressBar proBar;private NewsListAdapter adapter;private List<NewsListBean.Recent> mList = new ArrayList<>();private static final int REQUEST_EXTERNAL_STORAGE = 1;private static String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE};private ImageView menuBtn;private LinearLayoutManager layoutManager;private ImageView btnImg;private LinearLayout backLayoput;public static void verifyStoragePermissions(Activity activity) {int permission = ActivityCompat.checkSelfPermission(activity,Manifest.permission.WRITE_EXTERNAL_STORAGE);if (permission != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);}}private boolean isGrid = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);verifyStoragePermissions(MainActivity.this);initView();initData();menuBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {switchLayout();}});}private void switchLayout() {if (isGrid) {layoutManager = new LinearLayoutManager(this);adapter = new NewsListAdapter(R.layout.zh_item_layout, mList);zhLv.setAdapter(adapter);} else {layoutManager = new GridLayoutManager(this, 2);adapter = new NewsListAdapter(R.layout.zh_grid__item_layout, mList);zhLv.setAdapter(adapter);}zhLv.setLayoutManager(layoutManager);isGrid = !isGrid;}private void initView() {zhLv = findViewById(R.id.zh_lv);proBar = findViewById(R.id.progressbar);menuBtn = findViewById(R.id.btn_main_menu);btnImg = findViewById(R.id.btn_main_menu);backLayoput = findViewById(R.id.btn_back_layout);backLayoput.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {finish();}});layoutManager = new LinearLayoutManager(MainActivity.this);zhLv.setLayoutManager(layoutManager);adapter = new NewsListAdapter(R.layout.zh_item_layout, mList);zhLv.setAdapter(adapter);}private void initData() {proBar.setVisibility(View.VISIBLE);Retrofit retrofit = new Retrofit.Builder().baseUrl("https://news-at.zhihu.com/")//设置数据解析器.addConverterFactory(GsonConverterFactory.create()).build();ApiUrl apiUrl = retrofit.create(ApiUrl.class);Call<NewsListBean> call = apiUrl.getPic();call.enqueue(new Callback<NewsListBean>() {@Overridepublic void onResponse(Call<NewsListBean> call, Response<NewsListBean> response) {List<NewsListBean.Recent> recent = response.body().getRecent();if (response.body() != null && recent.size() > 0) {try {mList.addAll(recent);adapter.setNewData(mList);proBar.setVisibility(View.GONE);} catch (Exception e) {String message = e.getMessage();e.printStackTrace();}}}@Overridepublic void onFailure(Call<NewsListBean> call, Throwable t) {Log.e("mmm", "errow " + t.getMessage());}});}}

总结

一个小小的很实用的功能就完成了,下一篇文章会接着实现RecyclerView 吸顶效果,后续还会加上列表本地缓存等功能,Demo 在此系列文章完结附上,不妨点赞收藏哦~

青山不改,绿水长流 有缘江湖再见 ~

相关文章:

Android RecyclerView 之 列表宫格布局的切换

前言 RecyclerView 的使用我就不再多说&#xff0c;接下来的几篇文章主要说一下 RecyclerView 的实用小功能&#xff0c;包括 列表宫格的切换&#xff0c;吸顶效果&#xff0c;多布局效果等&#xff0c;今天这篇文章就来实现一下列表宫格的切换&#xff0c;效果如下 一、数据来…...

妈妈的爱依然深沉

村里的孩子为了买化肥&#xff0c;跟城里官老爷们借了好多钱。 那几年庄稼转手很快&#xff0c;不是用来吃的&#xff0c;因此借钱成本很高&#xff0c;大概LPR加100bp。 后来村里孩子终于发现庄稼终究只能用来吃&#xff0c;不再热衷买卖化肥。可是官老爷们的金融生意还要继续…...

net.ResolveTCPAddr(“tcp6“, address)

尝试解析 "www.google.com" 的IPv6地址。如果解析成功&#xff0c;程序将打印出解析后的IP地址、端口以及区域信息。如果解析失败&#xff0c;程序将打印出错误信息。 需要注意的是&#xff0c;如果 "www.google.com" 没有IPv6地址&#xff0c;或者本地网络…...

mysql和mybatisPlus实现:datetime类型的字段范围查询

前提说明 数据库在存储数据时,我们为了精确一下时间,便会把改时间类型的字段设置为datetime类型; 在过滤数据库数据时,我们又需要对该字段进行一个范围的过滤 由此,便出现了这篇博客 datetime数据类型 在MySQL中,datetime数据类型用于保存日期和时间的值。它的格式为Y…...

学习笔记:用ROS接收rosbag发布的topic

用ROS接收 bag.open发布的topic python语言 要使用ROS接收保存在rosbag文件中的话题消息&#xff0c;可以按照以下步骤进行操作&#xff1a; 1.首先&#xff0c;请确保你已经安装了ROS和相关的依赖。 2.创建一个ROS功能包&#xff08;或使用现有的功能包&#xff09;来处理…...

LAMP架构介绍配置命令讲解

LAMP架构介绍配置命令讲解 一、LAMP架构介绍1.1概述1.2LAMP各组件的主要作用1.3各组件的安装顺序 二、编译安装Apache httpd服务---命令讲解1、关闭防火墙&#xff0c;将安装Apache所需的软件包传到/opt/目录下2、安装环境依赖包3、配置软件模块4、编译安装5、优化配置文件路径…...

C语言之函数题

目录 1.乘法口诀表 2.交换两个整数 3.函数判断闰年 4.函数判断素数 5.计算斐波那契数 6.递归实现n的k次方 7.计算一个数的每位之和&#xff08;递归&#xff09; 8.字符串逆序&#xff08;递归实现&#xff09; 9.strlen的模拟&#xff08;递归实现&#xff09; 10.求…...

SpringBoot的四种handler类型

Controller ReuestMapping 实现Controller接口 使用Component将该类封装成一个Bean 实现HttpRequestHandler 实现RouterFunction...

基于KNN算法的鸢尾花种类预测

导入数据 iris_data load_iris() iris_data.data[0:5, :]array([[5.1, 3.5, 1.4, 0.2],[4.9, 3. , 1.4, 0.2],[4.7, 3.2, 1.3, 0.2],[4.6, 3.1, 1.5, 0.2],[5. , 3.6, 1.4, 0.2]])# 特征值名称 iris_data.feature_names[sepal length (cm),sepal width (cm),petal length (cm…...

英语-面试

自我介绍 hi,my name is tzh,26 years old.I major in software engineering. I participate in the design and development of the social project and e-commerce project. I master java and algorithm. Im familiar with gateway,spring,springboot,springcloud,redis…...

文件传输协议

文章目录 一、FTP1. 定义2. 端口3. 数据传输方式主动方式被动方式 二、TFTP三、常用命令 首先可以看下思维导图&#xff0c;以便更好的理解接下来的内容。 一、FTP 1. 定义 文件传输协议&#xff08;FTP&#xff09;是一种用于在客户端和服务器之间进行文件传输的标准网络协…...

Llama-2大模型本地部署研究与应用测试

最近在研究自然语言处理过程中&#xff0c;正好接触到大模型&#xff0c;特别是在年初chatgpt引来的一大波AIGC热潮以来&#xff0c;一直都想着如何利用大模型帮助企业的各项业务工作&#xff0c;比如智能检索、方案设计、智能推荐、智能客服、代码设计等等&#xff0c;总得感觉…...

白嫖idea

白嫖idea 地址 https://www.jetbrains.com/toolbox-app/...

PyCharm切换虚拟环境

PyCharm切换虚拟环境 为了满足不同任务需要不同版本的包&#xff0c;可以在Anaconda或者Miniconda创建多个虚拟环境文件夹&#xff0c;并在PyCharm下切换虚拟环境。 解决方案 1、打开Ananconda Prompt 2、创建自己的虚拟环境 格式&#xff1a;conda create -n 虚拟环境名字…...

自动化运维工具-----Ansible入门详解

目录 一.Ansible简介 什么是Ansible&#xff1f; Ansible的特点 Ansible的架构 二.Ansible任务执行解析 ansible任务执行模式 ansible执行流程 ansible命令执行过程 三.Ansible配置解析 ansible的安装方式 ansible的程序结构&#xff08;yum安装为例&#xff09; ansibl…...

一、Mycat2介绍与下载安装

第一章 入门概述 1.1 是什么 Mycat 是数据库中间件。 1、数据库中间件 中间件&#xff1a;是一类连接软件组件和应用的计算机软件&#xff0c;以便于软件各部件之间的沟 通。 例子&#xff1a;Tomcat&#xff0c;web中间件。 数据库中间件&#xff1a;连接java应用程序和数据库…...

链表的介绍

链表是一种常用的数据结构&#xff0c;它可以动态地添加、删除、查找和遍历元素。链表由多个节点组成&#xff0c;每个节点包括一个数据项和一个指向下一个节点的指针。这种数据结构可以高效地插入和删除元素&#xff0c;但相对于数组来说&#xff0c;查找元素的效率较低。 插…...

深度剖析:数据服务API的安全性与隐私保护

随着互联网技术的飞速发展&#xff0c;数据服务API已经成为了企业和个人获取、处理和分析数据的重要工具。然而&#xff0c;数据服务API的安全问题也日益凸显&#xff0c;尤其是在用户隐私保护方面。本文将深入剖析数据服务API的安全性与隐私保护问题&#xff0c;并结合产品FDL…...

MediaPlayer音频与视频的播放介绍

作者&#xff1a;向阳逐梦 Android多媒体中的——MediaPlayer&#xff0c;我们可以通过这个API来播放音频和视频该类是Androd多媒体框架中的一个重要组件&#xff0c;通过该类&#xff0c;我们可以以最小的步骤来获取&#xff0c;解码和播放音视频。 它支持三种不同的媒体来源…...

【Terraform学习】Terraform模块基础操作(Terraform模块)

本站以分享各种运维经验和运维所需要的技能为主 《python》&#xff1a;python零基础入门学习 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8》暂未更新 《docker学习》暂未更新 《ceph学习》ceph日常问题解…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...