com um clique
flutter-caching
Cache data in a Flutter app
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Menu
Cache data in a Flutter app
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Baseado na classificação ocupacional SOC
PocketMind 本地无头浏览器爬取架构,适用于小红书/知乎抓取、后台爬虫服务、MethodChannel、Cookie 管理与 MetadataManager 协作场景。
Use when implementing or debugging PocketMind mobile chat flows, including note-scoped sessions, global multi-session switching, sync gating, stream send behavior, and dialog interaction regressions.
PocketMind 后端 notes->resource_records->context_catalog 一致性改造专项 Skill。当用户讨论 resource_records 真相层、context_catalog 索引层、Outbox/Projector、检索 fallback、SessionCommit 长事务、transcript 重复同步或相关回归测试时必须触发。
Use when you need to understand or modify PocketMind note save to resource indexing flow, including outbox, MQ hint/DLQ compensation, projector consumption, and consistency boundaries.
PocketMind 移动端笔记同步架构专项 Skill。当涉及以下问题时必须触发:预览字段(previewTitle等)被同步覆盖、多端一致性与离线冲突问题、同步链路改造(Pull/Push)、UI层违规调用底层Provider、抓取/轮询等写入未进入同步队列、或维护同步守卫测试。
设计、重构和实现 PocketMind 项目中的整体上下文架构(Context Architecture),用于统一规划和落地 resources、user memories、agent memories、tenant skills、session、retrieval、ingestion、storage 与现有 Note/Chat/Asset 的边界。当用户要求为 PocketMind 新增长期记忆、重构 AI 上下文体系、借鉴 OpenViking 的上下文类型/层级/URI/存储/检索/会话思想,或需要分阶段实施 Context Service 时使用。
| name | flutter-caching |
| description | Cache data in a Flutter app |
| metadata | {"model":"models/gemini-3.1-pro-preview","last_modified":"Wed, 04 Mar 2026 18:37:11 GMT"} |
Implements advanced caching, offline-first data persistence, and performance optimization strategies in Flutter applications. Evaluates application requirements to select and integrate the appropriate local caching mechanism (in-memory, persistent, file system, or on-device databases). Configures Android-specific FlutterEngine caching to minimize initialization latency. Optimizes widget rendering, image caching, and scrolling performance while adhering to current Flutter API standards and avoiding expensive rendering operations.
Analyze the user's data retention requirements using the following decision tree to select the appropriate caching mechanism:
shared_preferences.sqflite). Proceed to Step 3.path_provider). Proceed to Step 2.cached_network_image or custom ImageCache). Proceed to Step 6.STOP AND ASK THE USER: "Based on your requirements, which data type and size are we handling? Should I implement SQLite, File System caching, or a different strategy?"
When shared_preferences is insufficient for larger data, use path_provider and dart:io to persist data to the device's hard drive.
import 'dart:io';
import 'package:path_provider/path_provider.dart';
class FileCacheService {
Future<String> get _localPath async {
// Use getTemporaryDirectory() for system-cleared cache
// Use getApplicationDocumentsDirectory() for persistent data
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/cached_data.json');
}
Future<File> writeData(String data) async {
final file = await _localFile;
return file.writeAsString(data);
}
Future<String?> readData() async {
try {
final file = await _localFile;
return await file.readAsString();
} catch (e) {
return null; // Cache miss
}
}
}
For large datasets requiring improved performance over simple files, implement an on-device database using sqflite.
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
class DatabaseService {
late Database _database;
Future<void> initDB() async {
_database = await openDatabase(
join(await getDatabasesPath(), 'app_cache.db'),
onCreate: (db, version) {
return db.execute(
'CREATE TABLE cache_data(id INTEGER PRIMARY KEY, key TEXT, payload TEXT)',
);
},
version: 1,
);
}
Future<void> insertCache(String key, String payload) async {
await _database.insert(
'cache_data',
{'key': key, 'payload': payload},
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
Future<String?> getCache(String key) async {
final List<Map<String, Object?>> maps = await _database.query(
'cache_data',
where: 'key = ?',
whereArgs: [key], // MUST use whereArgs to prevent SQL injection
);
if (maps.isNotEmpty) {
return maps.first['payload'] as String;
}
return null;
}
}
Combine local caching and remote fetching. Yield the cached data first (cache hit), then fetch from the network, update the cache, and yield the fresh data.
Stream<UserProfile> getUserProfile() async* {
// 1. Check local cache
final localData = await _databaseService.getCache('user_profile');
if (localData != null) {
yield UserProfile.fromJson(localData);
}
// 2. Fetch remote data
try {
final remoteData = await _apiClient.fetchUserProfile();
// 3. Update cache
await _databaseService.insertCache('user_profile', remoteData.toJson());
// 4. Yield fresh data
yield remoteData;
} catch (e) {
// Handle network failure; local data has already been yielded
}
}
To minimize Flutter's initialization time when adding Flutter screens to an Android app, pre-warm and cache the FlutterEngine.
Pre-warm in Application class (Kotlin):
class MyApplication : Application() {
lateinit var flutterEngine : FlutterEngine
override fun onCreate() {
super.onCreate()
flutterEngine = FlutterEngine(this)
// Optional: Configure initial route before executing entrypoint
flutterEngine.navigationChannel.setInitialRoute("/cached_route");
flutterEngine.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
)
FlutterEngineCache.getInstance().put("my_engine_id", flutterEngine)
}
}
Consume in Activity/Fragment (Kotlin):
// For Activity
startActivity(
FlutterActivity
.withCachedEngine("my_engine_id")
.backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent)
.build(this)
)
// For Fragment
val flutterFragment = FlutterFragment.withCachedEngine("my_engine_id")
.renderMode(FlutterView.RenderMode.texture)
.shouldAttachEngineToActivity(false)
.build()
Apply strict constraints to image caching and scrolling to prevent GPU memory bloat and layout passes.
ImageCache Validation:
Verify cache hits without triggering loads using containsKey.
class CustomImageCache extends ImageCache {
@override
bool containsKey(Object key) {
// Check if cache is tracking this key
return super.containsKey(key);
}
}
ScrollCacheExtent Implementation:
Use the strongly-typed ScrollCacheExtent object for scrolling widgets (replaces deprecated cacheExtent and cacheExtentStyle).
ListView(
// Use ScrollCacheExtent.pixels for pixel-based caching
scrollCacheExtent: const ScrollCacheExtent.pixels(500.0),
children: [ ... ],
)
Viewport(
// Use ScrollCacheExtent.viewport for fraction-based caching
scrollCacheExtent: const ScrollCacheExtent.viewport(0.5),
slivers: [ ... ],
)
Review the generated UI code for performance pitfalls.
saveLayer() triggers: Ensure Opacity, ShaderMask, ColorFilter, and Clip.antiAliasWithSaveLayer are only used when absolutely necessary. Replace Opacity with semitransparent colors or FadeInImage where possible.operator == overrides: Ensure operator == is NOT overridden on Widget objects unless they are leaf widgets whose properties rarely change.ListView and GridView use lazy builder methods (ListView.builder) and avoid intrinsic layout passes by setting fixed sizes where possible.whereArgs in sqflite queries. NEVER use string interpolation for SQL where clauses.FlutterEngine in Android, remember it outlives the Activity/Fragment. Explicitly call FlutterEngine.destroy() when it is no longer needed to clear resources.ImageCache.maxByteSize.operator == on widgets to force caching, as this degrades performance to O(N²). Rely on const constructors instead.cacheExtent (double) or cacheExtentStyle. ALWAYS use the ScrollCacheExtent object.isolates are not supported. Do not generate isolate-based background parsing for web targets.