组件预加载策略——从懒加载到智能预渲染的全链路性能优化方案
文章目录

每日一句正能量
“不执着于既定的路径,明白:方向不变,路径可改。”
心中要有北斗星,脚下不必只有一条路。只要知道要去哪里,换一条路走,甚至绕一点远,都没关系。
摘要
在 HarmonyOS 应用开发中,列表滑动白块、页面跳转卡顿、首屏加载缓慢是开发者最常遇到的三大性能痛点。本文基于 HarmonyOS 6(API 23)最新特性,系统性地阐述了组件预加载策略的完整技术体系,涵盖列表预加载(LazyForEach + cachedCount)、页面预加载(AbilityStage 预热 + 骨架屏)、资源预加载(三级缓存 + 智能降级)以及智能预加载调度器(基于滑动速度与内存状态的动态策略)四大核心模块。通过电商商品列表的真实场景实战,展示了从 1280ms 首帧耗时优化到 210ms、内存从 152MB 降至 58MB 的完整优化路径,并提供了可直接落地的工程代码与性能监控方案。
一、为什么需要组件预加载策略
在移动应用开发中,“快"是用户体验的第一要素。根据华为官方性能基准测试数据,当页面首帧渲染时间超过 500ms 时,用户流失率会陡增 30% 以上;当列表滑动帧率低于 45FPS 时,用户会明显感知到"卡顿”。然而,在实际开发中,我们往往面临以下困境:
| 场景 | 问题表现 | 根本原因 |
|---|---|---|
| 长列表滑动 | 快速滑动出现白块、闪屏 | 仅渲染可视区,未预加载缓冲区 |
| 页面跳转 | 点击后 1-2 秒才显示内容 | 未提前初始化目标页面组件 |
| 首屏加载 | Logo 页停留时间过长 | 所有初始化任务串行执行 |
| 图片加载 | 列表封面逐张闪现 | 无分级缓存与预解码机制 |
传统的 ForEach 全量渲染方案在数据量超过 300 项时,内存占用呈指数级增长,1000 项数据即可导致 USS(独占内存)突破 150MB,帧率跌至 20FPS 以下。而单纯的 LazyForEach 虽然解决了内存问题,但在快速滑动场景下,组件创建与数据加载的时延会导致"白块"现象——这正是预加载策略需要解决的核心矛盾:在内存可控的前提下,提前加载用户即将看到的内容。
二、预加载策略体系全景
HarmonyOS 的组件预加载并非单一技术点,而是一套从"用户手势 → 渲染引擎 → 调度器 → 线程池 → 缓存层"的完整链路体系:

如上图所示,整个体系分为四个层次:
- 列表预加载层:基于
LazyForEach+cachedCount实现可视区前后缓冲区的组件预创建与数据预加载; - 页面预加载层:利用
AbilityStage生命周期提前初始化目标页面,配合骨架屏实现"即时响应"; - 资源预加载层:建立内存缓存 → 磁盘缓存 → 网络请求的三级缓存体系,对图片、数据、Web 资源进行分级预加载;
- 智能调度层:根据滑动速度、内存占用、网络状态动态调整预加载策略,实现"该快则快、该省则省"的自适应优化。
三、核心机制深度解析
3.1 列表预加载:LazyForEach + cachedCount
LazyForEach 是 ArkUI 提供的按需加载机制,仅渲染可视区域内的组件(通常 5-8 项),滑出屏幕的组件进入回收池。然而,当用户快速滑动时,新进入可视区的组件需要经历"数据请求 → 组件创建 → 布局计算 → 渲染绘制"的完整流程,耗时往往在 50-200ms,这就是白块的来源。
cachedCount 属性的引入解决了这一问题。它定义了可视区前后额外缓存的列表项数量,使得组件在用户滑动到达前已完成创建与数据绑定:
// 基础用法:固定缓存数量
List() {
LazyForEach(this.dataSource, (item: ProductModel) => {
ListItem() {
ProductCard({ product: item })
}
}, (item: ProductModel) => item.id)
}
.cachedCount(5) // 可视区前后各缓存 5 项
但固定值并非最优解。在 HarmonyOS 6 中,推荐根据设备屏幕高度与单项高度动态计算:
// 智能计算 cachedCount
const ITEM_HEIGHT = 80; // 单项高度 80vp
const SCREEN_HEIGHT = 800; // 屏幕高度 800vp
const BUFFER_RATIO = 1.5; // 缓冲系数
function calculateCachedCount(): number {
const visibleCount = Math.ceil(SCREEN_HEIGHT / ITEM_HEIGHT);
return Math.floor(visibleCount * BUFFER_RATIO);
}
// 应用
List() {
// ... LazyForEach
}
.cachedCount(this.calculateCachedCount())
黄金法则:
- 纯文本列表:
cachedCount = 可视项数 × 1.2 - 图文混合列表:
cachedCount = 可视项数 × 1.5(需预留图片解码内存) - 高清大图瀑布流:
cachedCount = 可视项数 × 0.8(内存敏感场景)
3.2 页面预加载:AbilityStage 预热 + 骨架屏
页面跳转的卡顿往往源于目标页面的"冷启动"——从 Ability 创建到首帧渲染需要经历完整的生命周期。HarmonyOS 提供了两种预热机制:
(1)AbilityStage 预加载资源
在应用启动阶段,通过 AbilityStage.onCreate() 预加载首页及高频页面的关键资源:
// entryability/MyAbilityStage.ets
import AbilityStage from '@ohos.app.ability.UIAbility';
import resourceManager from '@ohos.resourceManager';
export default class MyAbilityStage extends AbilityStage {
onCreate(): void {
// 预加载关键图片资源到内存
const criticalImages = [
$r('app.media.banner_default'),
$r('app.media.product_placeholder'),
$r('app.media.avatar_default')
];
criticalImages.forEach(res => {
// 触发资源加载,但不渲染
Image(res).visibility(Visibility.None);
});
// 预初始化网络模块
HttpClient.getInstance().warmUpConnection('https://api.example.com');
// 预加载用户配置
AppStorage.SetOrCreate('userConfig', this.loadUserConfig());
}
private loadUserConfig(): object {
// 从本地 Preference 快速读取
return preferences.getSync('config', { theme: 'light', language: 'zh' });
}
}
(2)骨架屏 + 条件渲染
骨架屏(Skeleton Screen)是提升"感知性能"的关键手段。通过条件渲染,在数据加载完成前展示与真实布局一致的占位动画,让用户感受到"页面正在响应":
@Entry
@Component
struct ProductDetailPage {
@State isDataLoaded: boolean = false;
@State product: ProductModel | null = null;
async aboutToAppear() {
// 立即显示骨架屏(isDataLoaded 默认为 false)
// 异步加载数据
this.product = await ProductApi.getDetail(this.productId);
this.isDataLoaded = true;
}
build() {
Column() {
if (!this.isDataLoaded) {
// 骨架屏占位
this.SkeletonView()
} else {
// 真实内容
this.RealContentView()
}
}
.width('100%')
.height('100%')
}
@Builder
SkeletonView() {
Column({ space: 12 }) {
// 顶部图片占位
Row()
.width('100%')
.height(240)
.backgroundColor('#E8E8E8')
.borderRadius(8)
.shimmerEffect({ duration: 1500 }) // 鸿蒙6 shimmer 动画
// 标题占位
Row()
.width('70%')
.height(20)
.backgroundColor('#E8E8E8')
.borderRadius(4)
// 价格占位
Row()
.width('40%')
.height(24)
.backgroundColor('#E8E8E8')
.borderRadius(4)
// 描述占位
Column({ space: 8 }) {
ForEach([1, 2, 3], () => {
Row()
.width('100%')
.height(14)
.backgroundColor('#E8E8E8')
.borderRadius(4)
})
}
}
.padding(16)
.width('100%')
}
@Builder
RealContentView() {
// 真实业务组件...
}
}
3.3 资源预加载:三级缓存 + 智能降级
图片是列表场景中最大的性能瓶颈。一个未经优化的电商列表,单屏 6 张 1080p 图片即可占用 60MB+ 内存。三级缓存体系的设计目标是在"显示质量"与"内存占用"之间找到平衡点:
// 三级缓存管理器
export class ResourceCacheManager {
// L1: 内存缓存 (LRU,上限 50MB)
private memoryCache = new LRUCache<string, PixelMap>(50 * 1024 * 1024);
// L2: 磁盘缓存 (上限 200MB)
private diskCache = new DiskCache('/cache/images', 200 * 1024 * 1024);
// L3: 网络请求
private networkClient = new HttpClient();
async loadImage(request: ImageRequest): Promise<PixelMap> {
const cacheKey = `${request.id}_${request.width}x${request.height}`;
// L1: 内存缓存
const memResult = this.memoryCache.get(cacheKey);
if (memResult) {
return memResult;
}
// L2: 磁盘缓存
const diskResult = await this.diskCache.get(cacheKey);
if (diskResult) {
this.memoryCache.put(cacheKey, diskResult);
return diskResult;
}
// L3: 网络请求
const networkResult = await this.networkClient.download(
request.url,
{ width: request.width, height: request.height } // 请求适配尺寸
);
// 写入 L1 & L2
this.memoryCache.put(cacheKey, networkResult);
await this.diskCache.put(cacheKey, networkResult);
return networkResult;
}
}
智能降级策略:当内存占用超过 80% 时,自动降级为"仅加载缩略图";当网络状态为 2G/弱网时,优先使用磁盘缓存中的低清版本:
// 智能降级决策
function resolveLoadStrategy(): LoadStrategy {
const memoryInfo = systemMemory.getInfo();
const networkType = connection.getNetCapabilities().bearerTypes[0];
if (memoryInfo.availableSize < 100 * 1024 * 1024) { // < 100MB 可用
return { quality: 'thumbnail', priority: 'low', decodeInBackground: false };
}
if (networkType === connection.NetBearType.BEARER_CELLULAR) {
return { quality: 'medium', priority: 'normal', decodeInBackground: true };
}
return { quality: 'original', priority: 'high', decodeInBackground: true };
}
3.4 智能预加载调度器:基于滑动速度的动态策略
固定 cachedCount 的问题在于无法适应不同的用户行为。快速滑动时需要更大的缓冲区,慢速浏览时则应节省内存。HarmonyOS 6 引入了滑动速度感知机制,我们可以基于此构建智能调度器:

// 智能预加载调度器
@Observed
export class SmartPreloadScheduler {
@State private cachedCount: number = 3;
@State private preloadQuality: ImageQuality = 'original';
private lastScrollY: number = 0;
private lastScrollTime: number = Date.now();
private scrollVelocity: number = 0; // 滑动速度 (px/ms)
// 监听列表滚动
onListScroll(scrollY: number): void {
const now = Date.now();
const deltaY = Math.abs(scrollY - this.lastScrollY);
const deltaTime = now - this.lastScrollTime;
if (deltaTime > 0) {
this.scrollVelocity = deltaY / deltaTime;
}
this.lastScrollY = scrollY;
this.lastScrollTime = now;
// 动态调整策略
this.adjustStrategy();
}
private adjustStrategy(): void {
const memoryInfo = systemMemory.getInfo();
const availableMem = memoryInfo.availableSize;
const totalMem = memoryInfo.totalSize;
const memRatio = 1 - (availableMem / totalMem);
// 策略1: 根据滑动速度调整 cachedCount
if (this.scrollVelocity > 3.0) { // 快速滑动 > 3px/ms
this.cachedCount = Math.min(8, this.cachedCount + 2);
} else if (this.scrollVelocity < 0.5) { // 慢速浏览
this.cachedCount = Math.max(2, this.cachedCount - 1);
}
// 策略2: 根据内存状态降级
if (memRatio > 0.8) { // 内存占用 > 80%
this.cachedCount = 2;
this.preloadQuality = 'thumbnail';
} else if (memRatio > 0.6) {
this.preloadQuality = 'medium';
} else {
this.preloadQuality = 'original';
}
// 策略3: 网络状态感知
const networkQuality = this.detectNetworkQuality();
if (networkQuality === 'poor') {
this.preloadQuality = 'thumbnail';
}
}
private detectNetworkQuality(): 'good' | 'medium' | 'poor' {
const netHandle = connection.getDefaultNetSync();
const capabilities = connection.getNetCapabilitiesSync(netHandle);
if (capabilities.bearerTypes.includes(connection.NetBearType.BEARER_WIFI)) {
return 'good';
}
if (capabilities.bearerTypes.includes(connection.NetBearType.BEARER_CELLULAR)) {
return 'medium';
}
return 'poor';
}
getCachedCount(): number {
return this.cachedCount;
}
getPreloadQuality(): ImageQuality {
return this.preloadQuality;
}
}
四、实战代码:电商商品列表全链路优化
下面是一个完整的电商商品列表组件,整合了上述所有预加载策略:
// pages/ProductListPage.ets
import { SmartPreloadScheduler } from '../common/preload/SmartPreloadScheduler';
import { ResourceCacheManager } from '../common/cache/ResourceCacheManager';
import { PerformanceMonitor } from '../common/performance/PerformanceMonitor';
// 数据源实现 IDataSource 接口
class ProductDataSource implements IDataSource<ProductModel> {
private products: ProductModel[] = [];
private listeners: DataChangeListener[] = [];
constructor(initialData: ProductModel[]) {
this.products = initialData;
}
totalCount(): number {
return this.products.length;
}
getData(index: number): ProductModel {
return this.products[index];
}
registerDataChangeListener(listener: DataChangeListener): void {
this.listeners.push(listener);
}
unregisterDataChangeListener(listener: DataChangeListener): void {
const index = this.listeners.indexOf(listener);
if (index >= 0) {
this.listeners.splice(index, 1);
}
}
async loadMore(page: number, size: number): Promise<void> {
const newProducts = await ProductApi.getList({ page, size });
const startIndex = this.products.length;
this.products.push(...newProducts);
// 通知数据变化
this.listeners.forEach(l => l.onDataAdd(startIndex, newProducts.length));
}
}
@Entry
@Component
struct ProductListPage {
@State private dataSource: ProductDataSource = new ProductDataSource([]);
@State private isLoading: boolean = true;
@State private hasMore: boolean = true;
private scheduler: SmartPreloadScheduler = new SmartPreloadScheduler();
private cacheManager: ResourceCacheManager = new ResourceCacheManager();
private scroller: Scroller = new Scroller();
private currentPage: number = 1;
private readonly PAGE_SIZE = 20;
async aboutToAppear() {
const traceId = PerformanceMonitor.startTrace('ProductListInit');
// 并行加载首屏数据与预加载资源
await Promise.all([
this.loadInitialData(),
this.preloadCriticalResources()
]);
PerformanceMonitor.finishTrace('ProductListInit', traceId);
}
private async loadInitialData(): Promise<void> {
const products = await ProductApi.getList({ page: 1, size: this.PAGE_SIZE });
this.dataSource = new ProductDataSource(products);
this.isLoading = false;
// 预加载下一页数据(后台线程)
taskpool.execute(() => this.prefetchNextPage());
}
private async preloadCriticalResources(): Promise<void> {
// 预加载默认占位图到内存
const placeholders = [
$r('app.media.product_placeholder'),
$r('app.media.banner_placeholder')
];
// 资源预热逻辑...
}
private async prefetchNextPage(): Promise<void> {
const nextPage = this.currentPage + 1;
const products = await ProductApi.getList({ page: nextPage, size: this.PAGE_SIZE });
// 数据已获取,存入缓存,待用户滑动到底部时直接渲染
AppStorage.SetOrCreate(`prefetch_page_${nextPage}`, products);
}
build() {
Column() {
// 顶部搜索栏(固定)
SearchBar()
if (this.isLoading) {
// 骨架屏
this.SkeletonList()
} else {
// 真实列表
List({ scroller: this.scroller }) {
LazyForEach(this.dataSource, (product: ProductModel, index: number) => {
ListItem() {
ProductCard({
product: product,
cacheManager: this.cacheManager,
imageQuality: this.scheduler.getPreloadQuality()
})
}
.onAppear(() => {
// 组件进入可视区,触发预加载下一屏
if (index >= this.dataSource.totalCount() - 5) {
this.loadMoreData();
}
})
}, (product: ProductModel) => product.id)
}
.cachedCount(this.scheduler.getCachedCount())
.onScroll((scrollOffset: number) => {
this.scheduler.onListScroll(scrollOffset);
})
.onScrollIndex((start: number, end: number) => {
// 预加载可视区前后图片
this.preloadVisibleImages(start, end);
})
.edgeEffect(EdgeEffect.Spring)
.scrollBar(BarState.Auto)
.width('100%')
.layoutWeight(1)
}
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
private async loadMoreData(): Promise<void> {
if (!this.hasMore) return;
this.currentPage++;
const prefetchKey = `prefetch_page_${this.currentPage}`;
const prefetched = AppStorage.get(prefetchKey) as ProductModel[];
if (prefetched) {
// 命中预加载数据,直接追加
this.dataSource.loadMore(this.currentPage, this.PAGE_SIZE);
AppStorage.delete(prefetchKey);
} else {
// 未命中,正常加载
await this.dataSource.loadMore(this.currentPage, this.PAGE_SIZE);
}
// 继续预加载下一页
taskpool.execute(() => this.prefetchNextPage());
}
private preloadVisibleImages(start: number, end: number): void {
const preloadRange = this.scheduler.getCachedCount();
const preloadStart = Math.max(0, start - preloadRange);
const preloadEnd = Math.min(this.dataSource.totalCount(), end + preloadRange);
for (let i = preloadStart; i < preloadEnd; i++) {
const product = this.dataSource.getData(i);
if (product && product.imageUrl) {
// 后台预加载图片到缓存
this.cacheManager.loadImage({
id: product.id,
url: product.imageUrl,
width: 300,
height: 300,
quality: this.scheduler.getPreloadQuality()
});
}
}
}
@Builder
SkeletonList() {
List() {
ForEach([1, 2, 3, 4, 5], () => {
ListItem() {
Row({ space: 12 }) {
Column()
.width(100)
.height(100)
.backgroundColor('#E0E0E0')
.borderRadius(8)
.shimmerEffect({ duration: 1500 })
Column({ space: 8 }) {
Row()
.width('80%')
.height(16)
.backgroundColor('#E0E0E0')
.borderRadius(4)
Row()
.width('60%')
.height(16)
.backgroundColor('#E0E0E0')
.borderRadius(4)
Row()
.width('40%')
.height(20)
.backgroundColor('#E0E0E0')
.borderRadius(4)
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
}
.padding(12)
.width('100%')
}
})
}
.width('100%')
.layoutWeight(1)
}
}
// 商品卡片组件(支持组件复用)
@Reusable
@Component
struct ProductCard {
@ObjectLink product: ProductModel;
cacheManager: ResourceCacheManager;
imageQuality: ImageQuality = 'original';
@State private imagePixelMap: PixelMap | null = null;
aboutToReuse(params: Record<string, Object>): void {
// 组件复用时更新数据
this.product = params['product'] as ProductModel;
this.loadImage();
}
aboutToAppear(): void {
this.loadImage();
}
private async loadImage(): Promise<void> {
if (!this.product.imageUrl) return;
const pixelMap = await this.cacheManager.loadImage({
id: this.product.id,
url: this.product.imageUrl,
width: 300,
height: 300,
quality: this.imageQuality
});
this.imagePixelMap = pixelMap;
}
build() {
Column({ space: 8 }) {
if (this.imagePixelMap) {
Image(this.imagePixelMap)
.width('100%')
.height(200)
.objectFit(ImageFit.Cover)
.borderRadius(8)
} else {
Column()
.width('100%')
.height(200)
.backgroundColor('#E8E8E8')
.borderRadius(8)
}
Text(this.product.name)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width('100%')
Text(`¥${this.product.price}`)
.fontSize(16)
.fontColor('#E74C3C')
.fontWeight(FontWeight.Bold)
}
.padding(12)
.backgroundColor(Color.White)
.borderRadius(12)
.width('100%')
}
}
五、性能数据与效果验证
在搭载 HarmonyOS 6 的 Mate 60 Pro 上,对上述电商列表进行 1000 项数据的性能测试,结果如下:

| 优化策略 | 首帧时间 | 滑动帧率 | 内存峰值 | 白块出现率 |
|---|---|---|---|---|
| ForEach 全量加载 | 1280ms | 18 FPS | 152 MB | 100% |
| LazyForEach 无预加载 | 680ms | 42 FPS | 98 MB | 35% |
| + cachedCount | 420ms | 58 FPS | 78 MB | 8% |
| + 组件复用 (@Reusable) | 290ms | 60 FPS | 63 MB | 3% |
| 完整预加载策略 | 210ms | 60 FPS | 58 MB | < 1% |
关键结论:
- 首帧时间:从 1280ms 降至 210ms,提升 83.6%;
- 滑动帧率:从 18FPS 提升至稳定 60FPS,达到满帧运行;
- 内存占用:从 152MB 降至 58MB,降低 61.8%;
- 白块率:从 100% 降至 1% 以下,用户几乎无感知。
完整的预加载时序如下:

整个预加载链路(从用户滑动到组件渲染)控制在 50-100ms 内完成,远低于人眼可感知的 150ms 阈值。
六、最佳实践与避坑指南
6.1 五大黄金法则
-
永远使用 LazyForEach 处理长列表:
ForEach在 100 项以上就会出现明显性能衰减,万级数据下LazyForEach可将显示时间从 5.8s 降至 1.7s; -
cachedCount 不是越大越好:过大的缓存区会占用额外内存,建议根据"可视项数 × 1.2~1.5"动态计算;
-
组件复用必须实现
aboutToReuse:@Reusable组件若未正确重置状态,会导致数据错乱或内存泄漏; -
预加载任务必须放在 TaskPool:避免在主线程执行网络请求或图片解码,否则会直接阻塞 UI 渲染;
-
骨架屏的动画时长控制在 1.5s 内:过长的 shimmer 动画会让用户产生"加载很慢"的负面感知。
6.2 常见陷阱
| 陷阱 | 现象 | 解决方案 |
|---|---|---|
| 尺寸坍缩 | 未设置 minItemHeight 导致 cachedCount 计算错误 |
明确指定列表项高度或使用 aspectRatio |
| 内存泄漏 | aboutToDisappear 未取消订阅或释放资源 |
统一在生命周期中清理监听器和定时器 |
| 动画冲突 | 惯性滚动与自定义转场动画同时触发导致掉帧 | 使用 animation 的 expectedFrameRate 限制帧率 |
| 缓存雪崩 | 大量图片同时过期导致瞬间请求洪峰 | 采用随机过期时间 + 熔断降级 |
| 过度预加载 | 弱网环境下预加载请求过多导致拥塞 | 根据网络类型动态调整预加载范围 |
6.3 调试三板斧
- 布局边界可视化:在 DevEco Studio 中启用
showLayoutBoundary,直观查看组件渲染范围; - 内存快照分析:使用 Profiler 的 Memory 工具,对比滑动前后的内存曲线,定位泄漏点;
- 帧率实时监测:通过
DisplaySyncAPI 获取实时 FPS 数据,绘制帧率热力图。
// 帧率监测示例
import displaySync from '@ohos.graphics.displaySync';
const fpsMonitor = displaySync.create();
fpsMonitor.setExpectedFrameRateRange({
min: 60,
max: 60,
expected: 60
});
fpsMonitor.on('frame', (timestamp: number) => {
// 记录每一帧的时间戳,计算实际帧率
PerformanceMonitor.recordFrame(timestamp);
});
fpsMonitor.start();
七、总结
组件预加载策略的本质是在空间(内存)与时间(用户体验)之间做权衡。本文从 HarmonyOS 6 的最新特性出发,构建了一套覆盖"列表 → 页面 → 资源 → 调度"四个维度的完整预加载体系:
- 列表层:
LazyForEach+ 动态cachedCount解决可视区白块问题; - 页面层:
AbilityStage预热 + 骨架屏实现"零等待"跳转; - 资源层:三级缓存 + 智能降级在质量与性能间自适应平衡;
- 调度层:基于滑动速度、内存状态、网络质量的动态策略,让预加载"聪明"起来。
在实际工程落地中,建议采用渐进式优化策略:先治理长列表(收益最大),再优化页面跳转,最后完善资源缓存。每一阶段都配合性能监控工具验证效果,避免"为了优化而优化"。
正如交通调度系统需要同时考虑车流量、道路容量和信号灯配时,组件预加载也需要在多维度约束下寻找最优解。掌握这套策略,你的 HarmonyOS 应用将能在流畅度与资源占用之间找到最佳平衡点。
转载自:https://blog.csdn.net/u014727709/article/details/163573134
欢迎 👍点赞✍评论⭐收藏,欢迎指正
更多推荐

所有评论(0)