正如您在示例视频中看到的那样,当从左侧的空间中 Select 类别时,相应的项目就会显示在屏幕上.主要问题是切换类别时出现的延迟,即使图像已经加载和缓存.
我相信这种延迟是由从内存中检索缓存的图像所需的时间引起的.我try 过多种方法来预加载小部件,但所有try 都失败了.
在实验时,我碰巧查看了Chrome DevTools中的网络选项卡,并注意到图像是通过网络请求而不是从缓存进入的.CachedNetworks Image似乎功能不正常.
这是我关于cachedNetworks Image的代码.
Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.black, width: 2.0),
borderRadius: BorderRadius.circular(10.0)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: CachedNetworkImage(
key: ValueKey(tileData['imageCode']),
cacheKey: tileData['imageCode'],
imageUrl: widget.menuData['imageCode']
[tileData['imageCode']],
cacheManager: CustomCacheManager.instance,
fit: BoxFit.cover)))
class CustomCacheManager {
static const key = 'imageCache';
static CacheManager instance = CacheManager(
Config(
key,
stalePeriod: const Duration(days: 1),
maxNrOfCacheObjects: 100, // 최대 캐시 객체 수를 100개로 제한
repo: JsonCacheInfoRepository(databaseName: key),
fileService: HttpFileService(),
),
);
}
有完整代码
void _menuPreRender() {
_menuWidgets.clear();
for (Map<String, dynamic> category in _menuData['toManageList']) {
_menuWidgets[category['name']] = MenuView(
key: ValueKey(category['name']),
menuData: _menuData,
category: category['name'],
updateCallback: (int selectedMenuIndex) {
return () {
setState(() {
_selectedMenu = selectedMenuIndex;
_mainAreaWidget = _menuEdit(isEdit: true);
});
};
},
setManageMenuData: (Map<String, dynamic> data) {
_setManageMenuData(data);
});
}
}
/* ... */
class MenuView extends StatefulWidget {
const MenuView(
{super.key,
required this.menuData,
required this.category,
required this.updateCallback,
required this.setManageMenuData});
final String category;
final Map<String, dynamic> menuData;
final Function(int selectedMenuIndex) updateCallback;
final Function(Map<String, dynamic>) setManageMenuData;
@override
State<MenuView> createState() => _MenuViewState();
}
class _MenuViewState extends State<MenuView>
with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
@override
void didChangeDependencies() {
super.didChangeDependencies();
for (var menu in widget.menuData['toManage'][widget.category]['menu']) {
if (menu['imageCode'] != null && menu['imageCode'] != '') {
precacheImage(
NetworkImage(widget.menuData['imageCode'][menu['imageCode']]),
context);
}
}
}
@override
Widget build(BuildContext context) {
super.build(context);
print('category: ${widget.category}');
double screenHeight = MediaQuery.of(context).size.height;
return ReorderableListView.builder(
buildDefaultDragHandles: false,
itemCount: widget.menuData['toManage'][widget.category]['menu'].length,
itemBuilder: (context, index) {
Map<String, dynamic> tileData =
widget.menuData['toManage'][widget.category]['menu'][index];
return ListTile(
key: Key('$index'),
title: SizedBox(
height: screenHeight * 0.15,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
tileData['name'],
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 20),
),
const SizedBox(height: 5),
Text(
tileData['description'],
style:
const TextStyle(fontSize: 15, color: Colors.grey),
),
const SizedBox(height: 5),
Text(
'${tileData['price']}원',
style: const TextStyle(fontSize: 20),
),
],
),
SizedBox(
width: screenHeight * 0.14,
height: screenHeight * 0.14,
child: tileData['imageCode'] != null
? Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.black, width: 2.0),
borderRadius: BorderRadius.circular(10.0)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: CachedNetworkImage(
key: ValueKey(tileData['imageCode']),
cacheKey: tileData['imageCode'],
imageUrl: widget.menuData['imageCode']
[tileData['imageCode']],
cacheManager: CustomCacheManager.instance,
fit: BoxFit.cover)))
: const SizedBox.shrink()),
],
),
),
onTap: widget.updateCallback(index),
trailing: Container(
width: screenHeight * 0.08,
alignment: Alignment.bottomCenter, // Container 내부의 아이콘을 중앙에 배치
child: ReorderableDragStartListener(
index: index,
child: Icon(Icons.drag_handle_rounded,
size: screenHeight * 0.08)),
));
},
onReorder: (oldIndex, newIndex) {
List<Map<String, dynamic>> menuList =
widget.menuData['toManage'][widget.category]['menu'];
setState(() {
if (oldIndex < newIndex) {
newIndex -= 1;
}
final Map<String, dynamic> item = menuList.removeAt(oldIndex);
menuList.insert(newIndex, item);
});
widget.setManageMenuData(widget.menuData['toManage']);
},
);
}
}
我想要的是,在切换类别时,已经加载的图像能够立即向用户显示,没有任何延迟.我相信一定有办法实现这一点,因为许多商业应用程序都支持类似的功能.