Flutter瀑布流布局深度實踐:打造高性能動態圖片墻

本文將深入探討如何在Flutter中實現高性能瀑布流布局,解決動態高度內容展示的核心難題,并帶來卓越的用戶體驗。

引言:瀑布流布局的魅力

瀑布流布局(Pinterest-style layout)已成為現代應用展示圖片和內容的黃金標準。它通過錯落有致的排列方式,自適應內容高度的特點,以及無限滾動的交互體驗,為用戶創造了流暢自然的瀏覽感受。

在Flutter中實現高性能瀑布流需要解決幾個核心挑戰:動態高度計算、高效圖片加載、內存優化和流暢滾動體驗。本文將循序漸進地解決所有這些問題。

一、瀑布流實現的核心架構

1.1 組件結構設計

我們采用模塊化設計思想,將瀑布流拆分為三大核心組件:

WaterfallFlow(
items: items,// 數據源
columns: 2,// 列數
spacing: 16.0,// 列間距
itemBuilder: waterfallCard,// 自定義卡片構建器
onLoadMore: _loadMoreItems,// 滾動加載回調
)

1.2 瀑布流核心算法

關鍵算法在于將項目動態分配到各列中:

// 計算列寬
final columnWidth = (screenWidth - widget.spacing * (widget.columns - 1)) / widget.columns;// 創建列數組
final columns = List.generate(widget.columns, (index) => <dynamic>[]);// 循環分配項目到各列
for (int i = 0; i < widget.items.length; i++) {
columns[i % widget.columns].add(widget.items[i]);
}

這種簡單的循環分配算法保證了內容在各列之間均勻分布,同時保持高效的性能。

二、動態高度圖片處理的藝術

瀑布流的核心挑戰在于處理任意高度的圖片內容。我們使用IntrinsicHeight巧妙地解決這個問題:

2.1 AutoHeightImage組件

class _AutoHeightImage extends StatelessWidget {
final String imageUrl;
final double width;const _AutoHeightImage({required this.imageUrl, required this.width});
Widget build(BuildContext context) {
return CachedNetworkImage(
imageUrl: imageUrl,
width: width,
fit: BoxFit.cover,
placeholder: (context, url) => Container(
width: width,
height: width * 0.6,
color: Colors.grey[200],
),
errorWidget: (context, url, error) => Container(
width: width,
height: width * 0.6,
color: Colors.grey[200],
child: const Center(child: Icon(Icons.broken_image)),
),
imageBuilder: (context, imageProvider) {
return IntrinsicHeight(
child: Image(
image: imageProvider,
width: width,
fit: BoxFit.cover,
),
);
},
);
}
}

2.2 關鍵技術點解析

  1. IntrinsicHeight魔法:通過包裹Image組件,自動獲取圖片固有高度
  2. BoxFit.cover策略:保持圖片原始比例不變形
  3. 雙重占位機制
  • 加載前:灰色背景+默認寬高比
  • 加載失敗:優雅的錯誤展示
  1. 高效緩存:使用cached_network_image優化網絡加載

三、無限滾動與性能優化

3.1 滾動加載實現

void _scrollListener() {
if (_scrollController.position.pixels >=
_scrollController.position.maxScrollExtent - 200 &&
!_isLoading &&
widget.onLoadMore != null) {
_loadMoreItems();
}
}Future<void> _loadMoreItems() async {
if (_isLoading) return;setState(() => _isLoading = true);
try {
await widget.onLoadMore?.call();
} finally {
if (mounted) {
setState(() => _isLoading = false);
}
}
}

3.2 性能優化策略

  1. 緩存策略:使用CachedNetworkImage避免重復網絡請求
  2. 懶加載:距離底部200px時觸發加載,保持流暢體驗
  3. 狀態管理:精準控制加載狀態,避免重復請求
  4. 列表重建優化:使用不可變數據集合,避免不必要的重繪
  5. 滾動監聽銷毀:在dispose中釋放控制器資源

四、優雅的用戶體驗細節

4.1 美化卡片設計

Widget waterfallCard(BuildContext context, dynamic item, double width) {
return Card(
elevation: 3,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
margin: const EdgeInsets.only(bottom: 12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
// 圖片部分
ClipRRect(
borderRadius: const BorderRadius.vertical(top: Radius.circular(12)),
child: _AutoHeightImage(imageUrl: item['imageUrl'], width: width),
),// 文字內容
Padding(
padding: const EdgeInsets.all(12),
child: Column(/* 標題和描述 */),
),
],
),
);
}

4.2 回到頂部功能

Positioned(
bottom: 20,
right: 20,
child: FloatingActionButton(
onPressed: () => _scrollController.animateTo(0,
duration: const Duration(milliseconds: 500),
curve: Curves.easeOut),
child: const Icon(Icons.arrow_upward),
),
)

5.1 模擬數據生成

String getRandomImageUrl() {
final random = Random();
int randomNumber = random.nextInt(10);if (randomNumber < 2) {
return imageUrls[random.nextInt(imageUrls.length)];
} else {
int id = random.nextInt(1000) + 2;
return 'https://picsum.photos/300/200?random=$id';
}
}

這種混合數據源策略確保了:

  • 80%的圖片來自picsum.photos的隨機圖
  • 20%的圖片使用固定URL測試緩存性能
  • 部分卡片測試無標題/無描述的特殊情況

5.2 實際效果展示

在這里插入圖片描述

瀑布流布局在真實設備上的運行效果:滾動流暢、圖片加載自然、布局錯落有致

六、完整代碼結構

lib/
├── widgets/
│├── waterfall_flow_image_text.dart# 瀑布流核心組件
└── examples/
└── test_waterfall_flow_page.dart # 瀑布流示例頁面

test_waterfall_flow_page.dart

import 'package:flutter/material.dart';
import '../../widgets/waterfall_flow_image_text.dart';
import 'dart:math';
import 'package:cached_network_image/cached_network_image.dart';class WaterfallFlowExample extends StatefulWidget {const WaterfallFlowExample({Key? key}) : super(key: key);@overrideState<WaterfallFlowExample> createState() => _WaterfallFlowExampleState();
}class _WaterfallFlowExampleState extends State<WaterfallFlowExample> {List<Map<String, dynamic>> items = [];bool isLoading = false;int page = 1;@overridevoid initState() {super.initState();_loadInitialData();}void _loadInitialData() {setState(() {items = List.generate(30, (index) => _createItem(index));});}List<String> imageUrls = ['https://img0.baidu.com/it/u=933220220,287299241&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500','https://images.unsplash.com/photo-1461749280684-dccba630e2f6?auto=format&fit=crop&w=400&q=80',];String getRandomImageUrl() {final random = Random();int randomNumber = random.nextInt(10); // 0-9if (randomNumber < 2) {// Use imageUrls when random number is 0 or 1 (20% chance)return imageUrls[random.nextInt(imageUrls.length)];} else {// Use picsum.photos with random ID for numbers 2-9 (80% chance)int id = random.nextInt(1000) + 2; // Generates ID from 2 to 1001return 'https://picsum.photos/300/200?random=$id';}}Map<String, dynamic> _createItem(int id) {return {'id': id,'title': id == 0 ? '': '項目項目項目項目項目項目 $id','desc': id == 1 ? '':  '描述內容描述內容描述內容描述內容描述內容描述內容描述內容 $id',// 'imageUrl': 'https://picsum.photos/300/200?random=$id','imageUrl':getRandomImageUrl(),};}Future<void> _loadMoreItems() async {if (isLoading) return;setState(() => isLoading = true);await Future.delayed(const Duration(seconds: 1)); // 模擬網絡請求setState(() {final newItems = List.generate(5, (i) => _createItem(items.length + i));items = [...items, ...newItems]; // 創建新列表(保持不可變性)isLoading = false;});}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('瀑布流演示')),body: WaterfallFlow(items: items,columns: 2,spacing: 16.0,itemBuilder: waterfallCard,onLoadMore: _loadMoreItems, // 傳入加載更多回調),// body: Center(//   child: Column(//     mainAxisAlignment: MainAxisAlignment.center,//     children: [//       const Text('Image.network1:', style: TextStyle(fontWeight: FontWeight.bold)),//       Image.network('https://picsum.photos/250?image=9'),//       const Text('Image.network2:', style: TextStyle(fontWeight: FontWeight.bold)),//       Image.network(//         'https://docs.flutter.dev/assets/images/dash/dash-fainting.gif',//       ),//       // 調試塊1:基本圖片//       const Text('基本網絡圖片:', style: TextStyle(fontWeight: FontWeight.bold)),//       Container(//         color: Colors.yellow, // 調試背景//         padding: const EdgeInsets.all(8),//         child: SizedBox(//           width: 300,//           height: 200,//           child: Image.network(//             'https://img0.baidu.com/it/u=933220220,287299241&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',//             loadingBuilder: (context, child, progress) {//               if (progress == null) return child;//               return const Center(child: CircularProgressIndicator());//             },//             errorBuilder: (context, error, stack) {//               print('Image.network錯誤: $error');//               return const Icon(Icons.error, size: 50);//             },//           ),//         ),//       ),////       const SizedBox(height: 20),////       // 調試塊2:CachedNetworkImage//       const Text('CachedNetworkImage:', style: TextStyle(fontWeight: FontWeight.bold)),//       // 使用 Expanded 包裹整個容器//       Expanded(//         child: Container(//           color: Colors.blue[100],//           padding: const EdgeInsets.all(8),//           child: CachedNetworkImage(//             imageUrl: 'https://images.unsplash.com/photo-1506744038136-46273834b3fb?auto=format&fit=crop&w=400&q=80',//             placeholder: (context, url) => const Center(child: CircularProgressIndicator()),//             errorWidget: (context, url, error) {//               print('CachedNetworkImage錯誤: $error');//               return const Icon(Icons.error, size: 50);//             },//             fit: BoxFit.cover, // 確保圖片填充可用空間//           ),//         ),//       ),//     ],//   ),// ),);}
}

waterfall_flow_image_text.dart

import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';class WaterfallFlow extends StatefulWidget {final List<Map<String, dynamic>> items;final int columns;final double spacing;final Widget Function(BuildContext, dynamic, double) itemBuilder;final Future<void> Function()? onLoadMore;const WaterfallFlow({super.key,required this.items,this.columns = 2,this.spacing = 12.0,required this.itemBuilder,this.onLoadMore,});@overrideState<WaterfallFlow> createState() => _WaterfallFlowState();
}class _WaterfallFlowState extends State<WaterfallFlow> {final ScrollController _scrollController = ScrollController();bool _isLoading = false;@overridevoid initState() {super.initState();_scrollController.addListener(_scrollListener);}void _scrollListener() {if (_scrollController.position.pixels >=_scrollController.position.maxScrollExtent - 200 &&!_isLoading &&widget.onLoadMore != null) {_loadMoreItems();}}Future<void> _loadMoreItems() async {if (_isLoading) return;setState(() => _isLoading = true);try {await widget.onLoadMore?.call();} finally {if (mounted) {setState(() => _isLoading = false);}}}@overrideWidget build(BuildContext context) {final screenWidth = MediaQuery.of(context).size.width;final columnWidth =(screenWidth - widget.spacing * (widget.columns - 1)) / widget.columns;// 簡單按順序分配項目到各列final columns = List.generate(widget.columns, (index) => <dynamic>[]);for (int i = 0; i < widget.items.length; i++) {columns[i % widget.columns].add(widget.items[i]);}return Stack(children: [ListView(controller: _scrollController,children: [Row(crossAxisAlignment: CrossAxisAlignment.start,children: List.generate(widget.columns, (columnIndex) {return Container(width: columnWidth,margin: EdgeInsets.only(right: columnIndex < widget.columns - 1 ? widget.spacing : 0),child: Column(crossAxisAlignment: CrossAxisAlignment.stretch,children: [for (var item in columns[columnIndex])widget.itemBuilder(context, item, columnWidth),],),);}),),if (_isLoading)const Padding(padding: EdgeInsets.all(16.0),child: Center(child: CircularProgressIndicator()),),],),Positioned(bottom: 20,right: 20,child: FloatingActionButton(onPressed: () => _scrollController.animateTo(0,duration: const Duration(milliseconds: 500),curve: Curves.easeOut),backgroundColor: Colors.blue,child: const Icon(Icons.arrow_upward, color: Colors.white),),),],);}@overridevoid dispose() {_scrollController.dispose();super.dispose();}
}// 瀑布流卡片 - 完全動態高度
Widget waterfallCard(BuildContext context, dynamic item, double width) {return Card(elevation: 3,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12),),margin: const EdgeInsets.only(bottom: 12),child: Column(crossAxisAlignment: CrossAxisAlignment.start,mainAxisSize: MainAxisSize.min,children: [// 圖片部分 - 使用IntrinsicHeight保持比例ClipRRect(borderRadius: const BorderRadius.vertical(top: Radius.circular(12)),child: _AutoHeightImage(imageUrl: item['imageUrl'],width: width,),),// 文字內容部分Padding(padding: const EdgeInsets.all(12),child: Column(crossAxisAlignment: CrossAxisAlignment.start,mainAxisSize: MainAxisSize.min,children: [if (item['title']?.isNotEmpty == true)Padding(padding: const EdgeInsets.only(bottom: 6),child: Text(item['title'],style: const TextStyle(fontSize: 16,fontWeight: FontWeight.bold,),maxLines: 2,overflow: TextOverflow.ellipsis,),),if (item['desc']?.isNotEmpty == true)Text(item['desc'],style: TextStyle(color: Colors.grey[600],fontSize: 14,),maxLines: 2,overflow: TextOverflow.ellipsis,),],),),],),);
}// 自動高度圖片組件
class _AutoHeightImage extends StatelessWidget {final String imageUrl;final double width;const _AutoHeightImage({required this.imageUrl,required this.width,});@overrideWidget build(BuildContext context) {return CachedNetworkImage(imageUrl: imageUrl,width: width,fit: BoxFit.cover,placeholder: (context, url) => Container(width: width,height: width * 0.6, // 默認比例color: Colors.grey[200],child: const Center(child: CircularProgressIndicator()),),errorWidget: (context, url, error) => Container(width: width,height: width * 0.6,color: Colors.grey[200],child: const Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Icon(Icons.broken_image, size: 40, color: Colors.grey),SizedBox(height: 8),Text('加載失敗', style: TextStyle(color: Colors.grey)),],),),),imageBuilder: (context, imageProvider) {return IntrinsicHeight(child: Image(image: imageProvider,width: width,fit: BoxFit.cover,),);},);}
}

七、Flutter圖片加載失敗

🔧 步驟1:徹底重置設備網絡棧(關鍵!)
# 終止所有ADB進程
adb kill-server# 清除DNS緩存和網絡設置
adb shell settings delete global captive_portal_mode
adb shell settings delete global captive_portal_server
adb shell settings put global captive_portal_mode 0
adb shell settings put global captive_portal_detection_enabled 0
adb shell ndc resolver flushdefaultif
adb shell ndc resolver clearnetdns# 強制使用Google DNS
adb shell ndc resolver setdefaultif eth0
adb shell ndc resolver setifdns eth0 8.8.8.8 8.8.4.4# 重啟網絡接口
adb shell svc wifi disable
adb shell svc data disable
sleep 3# 等待網絡完全關閉
adb shell svc wifi enable
adb shell svc data enable# 重啟ADB服務
adb start-server

原理:Android系統DNS緩存污染是圖片加載失敗的常見元兇,此操作徹底清理網絡狀態,解決80%的偶發性問題。


🔐 步驟2:修改網絡安全配置

android/app/src/main/res/xml/network_security_config.xml 中添加:

<network-security-config>
<!-- 允許HTTP明文傳輸 -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system"/>
<certificates src="user"/>
</trust-anchors>
</base-config><!-- 專門放行圖片CDN域名 -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">*.picsum.photos</domain>
<domain includeSubdomains="true">*.unsplash.com</domain>
<domain includeSubdomains="true">*.baidu.com</domain>
<trust-anchors>
<certificates src="system"/>
<certificates src="user"/>
</trust-anchors>
</domain-config>
</network-security-config>

注意:在 AndroidManifest.xml 中啟用此配置:

<uses-permission android:name="android.permission.INTERNET" />
<application
android:usesCleartextTraffic="true"
android:networkSecurityConfig="@xml/network_security_config"
... >

結語:瀑布流的藝術與科學

通過本文的實踐,我們成功打造了一個高性能的Flutter瀑布流組件。關鍵點在于:

  1. 使用IntrinsicHeight解決動態高度問題
  2. 結合CachedNetworkImage實現高效圖片加載
  3. 精準控制滾動加載邏輯
  4. 注重用戶體驗細節

這些技術的結合使得我們的瀑布流不僅在視覺上吸引人,而且在性能上表現出色。隨著Flutter的不斷發展,我們可以期待更多優化瀑布流的方案出現,但本文的核心思想和方法論將長期有效。

最好的UI是看不見的UI——當用戶沉浸在你的內容中而沒有注意到布局本身時,說明你的瀑布流實現達到了完美境界。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/89223.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/89223.shtml
英文地址,請注明出處:http://en.pswp.cn/web/89223.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OpenCV 伽馬校正函數gammaCorrection()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 該函數用于對輸入圖像應用伽馬校正&#xff08;Gamma Correction&#xff09;&#xff0c;這是一種非線性的圖像處理技術&#xff0c;主要用于調整…

Linux-局域網構建+VLAN 劃分 + 端口 MAC-IP 綁定 + 靜態 DHCP

文章目錄1. 適用于家庭、工作室或小型企業的局域網構建2. VLAN劃分3. VLAN 劃分 端口 MAC-IP 綁定 靜態 DHCP跳轉→網絡管理基礎復習 1. 適用于家庭、工作室或小型企業的局域網構建 ? 一、硬件連線&#xff08;一次到位&#xff09; 光纖入戶 → 光貓/寬帶調制解調器光貓…

滲透測試路線

滲透測試學習路線報告&#xff08;從入門到高級&#xff09; 引言&#xff1a;滲透測試概述與學習路線設計 滲透測試作為網絡安全體系中的核心實踐環節&#xff0c;通過模擬真實攻擊者的技術手段與攻擊路徑&#xff0c;主動識別信息系統中的安全漏洞、評估防護機制有效性&#…

Node.js 中http 和 http/2 是兩個不同模塊對比

1. 核心模塊對比 特性http 模塊 (HTTP/1.1)http2 模塊 (HTTP/2)協議版本HTTP/1.1&#xff08;文本協議&#xff09;HTTP/2&#xff08;二進制協議&#xff09;多路復用不支持&#xff08;需多個 TCP 連接&#xff09;支持&#xff08;單連接多流&#xff09;頭部壓縮無HPACK 壓…

3DGS之COLMAP

COLMAP 在 3DGS 中起到了數據預處理和三維重建的關鍵作用&#xff0c;其處理流程包括特征提取與匹配、稀疏重建、稠密重建和輸出文件生成。結合 3DGS 的高斯分布建模和優化算法&#xff0c;COLMAP 提供了場景的幾何和相機信息&#xff0c;為實時渲染和三維重建奠定了基礎。一、…

RabbitMQ中隊列長度限制(Queue Length Limit)詳解

在 RabbitMQ 中&#xff0c;隊列長度限制&#xff08;Queue Length Limit&#xff09;是指對隊列中消息數量的最大限制。當隊列中的消息數量達到設定的上限時&#xff0c;RabbitMQ 會根據配置的策略&#xff08;如丟棄舊消息、拒絕新消息或將消息轉移到另一個隊列&#xff09;來…

Python設計模式深度解析:建造者模式(Builder Pattern)完全指南

Python設計模式深度解析&#xff1a;建造者模式&#xff08;Builder Pattern&#xff09;完全指南前言什么是建造者模式&#xff1f;建造者模式的核心思想模式的核心組成實際案例一&#xff1a;UI選擇組件的動態構建抽象建造者基類具體建造者實現列表框建造者復選框建造者工廠建…

elementuiPlus+vue3手腳架后臺管理系統,上生產環境之后,如何隱藏vite.config.ts的target地址

在項目根目錄創建 .env.production 文件&#xff1a; VITE_API_TARGEThttps://your-real-api.com修改 vite.config.ts&#xff1a; import { defineConfig, loadEnv } from viteexport default defineConfig(({ mode }) > {const env loadEnv(mode, process.cwd(), )return…

ARCGIS PRO DSK 顏色選擇控件(ColorPickerControl)的調用

顏色選擇控件ColorPickerControl 。一、XAML 集成方式 1 、在WPF窗體上使用&#xff0c;xml&#xff1a;加入空間命名引用xmlns:ui1"clr-namespace:ArcGIS.Desktop.Internal.Mapping.Symbology;assemblyArcGIS.Desktop.Mapping" xmlns:uil"http://schemas.xceed…

深淺拷貝以及函數緩存

目錄 數據類型介紹 基本數據類型&#xff08;Primitive Types&#xff09; 引用數據類型&#xff08;Reference Types&#xff09; 淺拷貝 深拷貝 利用JSON的序列化和反序列化實現深拷貝 遞歸實現深拷貝 第三方庫lodash的cloneDeep 函數緩存的概念 實現方法 數據類型介…

第六屆信號處理與計算機科學國際學術會議(SPCS 2025)

重要信息 官網&#xff1a;www.icspcs.org &#xff08;詳情見官網&#xff09; 時間&#xff1a;2025年8月15-17日 地點&#xff1a;西安 主題 信號處理與智能計算計算科學與人工智能網絡與多媒體技術數字信號處理 雷達信號處理 通信信號處理 臨時和傳感器網絡 模擬和…

MongoDB:一個靈活的、可擴展的 NoSQL 數據庫

&#x1f90d; 前端開發工程師、技術日更博主、已過CET6 &#x1f368; 阿珊和她的貓_CSDN博客專家、23年度博客之星前端領域TOP1 &#x1f560; 牛客高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》、《前端求職突破計劃》 &#x1f35a; 藍橋云課簽約作者、…

系統思考場景應用

最近一直在與不同行業頭部企業共同探討系統思考這個主題。一些新的合作伙伴也常常問我&#xff0c;系統思考究竟能為客戶解決什么痛點&#xff1f; 這兩天上課客戶的核心需求是&#xff1a;全局思維。在過去的幾年里&#xff0c;我深切體會到&#xff0c;隨著外部環境的快速變化…

SQL預編譯:安全高效數據庫操作的關鍵

通過占位符&#xff08;如 ? 或命名參數&#xff09;編寫預編譯的 SQL 語句&#xff08;通常通過 PreparedStatement 實現&#xff09;是數據庫操作的最佳實踐&#xff0c;主要好處包括&#xff1a;&#x1f512; 1. 防止 SQL 注入攻擊&#xff08;核心安全優勢&#xff09; 問…

springboot實驗室管理系統-計算機畢業設計源碼20916

摘 要 隨著高校實驗室管理需求的不斷增加&#xff0c;傳統的管理方式已經難以滿足現代教育的要求。為了解決這一問題&#xff0c;本文設計并實現了一種基于VUE和SpringBoot的實驗室管理系統。該系統采用前后端分離的架構&#xff0c;前端使用VUE框架&#xff0c;后端基于Sprin…

spdringboot共享學習室小程序 計算機畢業設計源碼27728

摘 要 共享學習室小程序是一款基于SpringBoot框架開發的移動端應用&#xff0c;旨在提供一個便捷的自習室預約、管理和資源共享平臺。通過該小程序&#xff0c;用戶可以方便地預約自習室、查看資訊、提交反饋意見&#xff0c;同時進行失物招領、查看訂單信息等多項操作。對于管…

JVM——JVM 的內存區域是如何劃分的?

Java 虛擬機運行時數據區分為方法區、堆、虛擬機棧、本地方法棧、程序計數器。 方法區(Method Area): [1] 存儲類信息、常量、靜態變量和即時編譯器(JIT)編譯后的代碼。 [2] 屬于線程共享區域&#xff0c;所有線程共享方法區內存 [3] 在 JDK8之前&#xff0c;HotSpot使用永久代…

SpringAi筆記

簡介 :: Spring AI 中文文檔 Spring AI 解決了 AI 集成的根本難題&#xff1a;將企業數據和 API 與 AI 模型連接起來。 聊天客戶端 API (ChatClient ) 發起對模型的調用和響應 創建&#xff1a;其中可以通過bean來注入創建好的chatClient 可以使用Qualifier注解&#xff0c;…

基于SD-WAN的智慧高速解決方案:高效、低成本的智能交通實踐

隨著交通網絡的智能化需求逐漸增加&#xff0c;智慧高速建設已成為提升通行效率、優化安全性、實現交通現代化管理的重要方向。在本文中&#xff0c;我們將以某智慧高速項目為例&#xff0c;詳細探討如何通過 SD-WAN 技術與多種智能化手段結合&#xff0c;實現“低成本、高效率…

Towards Low Light Enhancement with RAW Images 論文閱讀

利用 RAW 圖像實現低光增強 摘要 在本文中&#xff0c;我們首次進行了基準研究&#xff0c;詳細闡述了在低光增強中使用 RAW 圖像的優越性&#xff0c;并提出了一種新穎的替代方案&#xff0c;以更靈活和實用的方式利用 RAW 圖像。受對典型圖像處理流程的全面考慮啟發&#xff…