nkds

导航

 

MonkeyCode移动端与跨平台开发指南:一套代码,全平台运行

前言

在移动互联网时代,"一次编写,到处运行"是每个开发者的梦想。从早期的PhoneGap到React Native,再到Flutter和Uni-app,跨平台开发技术不断演进。而MonkeyCode作为新一代AI编程助手,正在为跨平台开发带来革命性的变化——它不仅能帮你生成各平台的代码,还能智能处理平台差异、优化性能、甚至自动适配不同屏幕尺寸。

本文将全面介绍如何使用MonkeyCode进行移动端和跨平台应用开发,涵盖React Native、Flutter、Uni-app、Taro等主流框架的实战指南。


一、跨平台开发现状与挑战

1.1 主流跨平台技术对比

框架 开发语言 渲染方式 性能 生态成熟度 学习曲线 社区活跃度
React Native JavaScript/TypeScript 原生组件 ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐
Flutter Dart 自绘引擎(Skia) ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐
Uni-app Vue/JavaScript 混合渲染 ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐
Taro React/Vue 多端编译 ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
Capacitor TypeScript/Web 原生WebView ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
Kotlin Multiplatform Kotlin 原生共享逻辑 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐

1.2 跨平台开发的常见痛点

┌─────────────────────────────────────────────────────────────┐
│              跨平台开发者日常痛苦指数 😩                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  🔴 痛点Top 5:                                              │
│                                                             │
│  1️⃣ 平台差异适配 (痛苦指数: ████████████ 10/10)             │
│     "iOS上好好的,Android就崩了"                             │
│     "iPhone X的刘海屏怎么适配?"                              │
│                                                             │
│  2️⃣ 性能优化 (痛苦指数: ██████████░░ 8/10)                  │
│     "列表滚动卡顿怎么办?"                                    │
│     "内存占用太高被系统杀掉了"                                 │
│                                                             │
│  3️⃣ 原生模块桥接 (痛苦指数: █████████░░░ 7/10)              │
│     "需要调用原生相机功能..."                                 │
│     "这个第三方SDK只有原生版本"                                │
│                                                             │
│  4️⃣ 多端状态管理 (痛苦指数: ████████░░░░ 6/10)              │
│     "H5和小程序的状态要分别维护"                               │
│     "数据同步是个噩梦"                                        │
│                                                             │
│  5️⃣ 调试困难 (痛苦指数: ████████░░░░ 6/10)                  │
│     "错误信息看不懂"                                          │
│     "真机调试连接不上"                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

二、MonkeyCode如何赋能跨平台开发

2.1 核心能力矩阵

┌─────────────────────────────────────────────────────────────┐
│           MonkeyCode 跨平台开发能力矩阵                      │
├──────────────────┬─────────┬─────────┬─────────┬─────────────┤
│ 能力维度         │ RN      │ Flutter │ Uni-app │ Taro        │
├──────────────────┼─────────┼─────────┼─────────┼─────────────┤
│ 代码生成         │ ✅✅✅   │ ✅✅✅   │ ✅✅✅   │ ✅✅✅       │
│ 平台差异处理     │ ✅✅✅   │ ✅✅✅   │ ✅✅    │ ✅✅         │
│ 性能优化建议     │ ✅✅✅   │ ✅✅✅   │ ✅✅    │ ✅✅         │
│ 原生模块集成     │ ✅✅     │ ✅✅     │ ✅✅    │ ✅          │
│ UI组件生成       │ ✅✅✅   │ ✅✅✅   │ ✅✅✅   │ ✅✅✅       │
│ 状态管理方案     │ ✅✅✅   │ ✅✅✅   │ ✅✅    │ ✅✅         │
│ API对接          │ ✅✅✅   │ ✅✅✅   │ ✅✅✅   │ ✅✅✅       │
│ 测试用例生成     │ ✅✅     │ ✅✅     │ ✅✅    │ ✅          │
│ 迁移辅助         │ ✅✅     │ ✅✅     │ ✅✅✅   │ ✅✅✅       │
│ 文档生成         │ ✅✅✅   │ ✅✅✅   │ ✅✅✅   │ ✅✅✅       │
└──────────────────┴─────────┴─────────┴─────────┴─────────────┘

2.2 MonkeyCode跨平台工作流

                    MonkeyCode 跨平台开发工作流
                    
需求描述 (自然语言)
    │
    ▼
┌─────────────────┐
│  AI 需求分析     │ ← 理解业务需求,识别平台特性
└────────┬────────┘
         │
         ▼
┌─────────────────┐     ┌─────────────────┐
│  代码生成        │────▶│  平台适配层      │
│  (核心逻辑)      │     │  (差异化处理)    │
└────────┬────────┘     └────────┬────────┘
         │                       │
         ▼                       ▼
┌─────────────────┐     ┌─────────────────┐
│  UI组件生成      │     │  原生模块桥接    │
│  (响应式布局)    │     │  (设备能力)      │
└────────┬────────┘     └────────┬────────┘
         │                       │
         └───────────┬───────────┘
                     ▼
            ┌─────────────────┐
            │  代码审查与优化  │ ← 性能+质量检查
            └────────┬────────┘
                     ▼
            ┌─────────────────┐
            │  多端输出        │ → iOS / Android / H5 / 小程序
            └─────────────────┘

三、React Native + MonkeyCode 实战

3.1 项目初始化与配置

# 使用MonkeyCode快速初始化RN项目
monkeycode init rn MyApp \
  --typescript \
  --navigation react-navigation-6 \
  --state zustand \
  --styling nativeWind \
  --testing jest+detox

# 项目结构预览
MyApp/
├── src/
│   ├── components/      # 公共组件
│   ├── screens/         # 页面
│   ├── navigation/      # 导航配置
│   ├── hooks/           # 自定义Hooks
│   ├── stores/          # 状态管理
│   ├── services/        # API服务
│   ├── utils/           # 工具函数
│   ├── types/           # 类型定义
│   └── assets/          # 静态资源
├── android/
├── ios/
├── __tests__/
└── App.tsx

3.2 AI驱动的组件开发

场景:创建一个响应式商品卡片组件

// ProductCard.tsx - 使用MonkeyCode生成的响应式商品卡片
// 提示词: "创建一个支持iOS和Android的商品卡片组件,
//         包含图片、标题、价格、评分,支持暗色模式,
//         图片使用缓存加载,点击有水波纹效果"

import React, { memo } from 'react';
import {
  View,
  Text,
  Image,
  StyleSheet,
  TouchableOpacity,
  Pressable,
  Platform,
} from 'react-native';
import { useTheme } from '../hooks/useTheme';

interface ProductCardProps {
  id: string;
  title: string;
  price: number;
  originalPrice?: number;
  image: string;
  rating: number;
  salesCount: number;
  onPress?: (id: string) => void;
}

/**
 * 商品卡片组件
 * - 支持iOS/Android双平台
 * - 自动适配暗色模式
 * - 图片懒加载+缓存
 * - 点击反馈效果(平台差异化)
 */
const ProductCard = memo<ProductCardProps>(({
  id,
  title,
  price,
  originalPrice,
  image,
  rating,
  salesCount,
  onPress,
}) => {
  const { colors, isDark } = useTheme();

  const formatPrice = (p: number): string => {
    return `¥${(p / 100).toFixed(2)}`;
  };

  const renderStars = (): string => {
    return '★'.repeat(Math.floor(rating)) + '☆'.repeat(5 - Math.floor(rating));
  };

  const CardWrapper = onPress ? Pressable : View;

  return (
    <CardWrapper
      style={[
        styles.container,
        { backgroundColor: colors.card },
        isDark && styles.containerDark,
      ]}
      onPress={() => onPress?.(id)}
      android_ripple={{ color: colors.ripple, borderless: false }}
      // iOS使用opacity动画作为点击反馈
      style={({ pressed }) => [
        styles.container,
        { backgroundColor: colors.card, opacity: pressed ? 0.9 : 1 },
      ]}>
      
      {/* 商品图片 */}
      <Image
        source={{ uri: image }}
        style={styles.image}
        resizeMode="cover"
        // MonkeyCode建议: 使用FastImage替代以获得更好的性能
        cachePolicy="cacheFirst"
      />
      
      {/* 商品信息 */}
      <View style={styles.infoContainer}>
        {/* 标题 */}
        <Text 
          numberOfLines={2} 
          style={[styles.title, { color: colors.text }]}>
          {title}
        </Text>
        
        {/* 评分和销量 */}
        <View style={styles.metaRow}>
          <Text style={[styles.rating, { color: colors.warning }]}>
            {renderStars()} {rating.toFixed(1)}
          </Text>
          <Text style={[styles.sales, { color: colors.textSecondary }]}>
            已售{salesCount > 10000 ? `${(salesCount / 10000).toFixed(1)}万` : salesCount}
          </Text>
        </View>
        
        {/* 价格区域 */}
        <View style={styles.priceRow}>
          <Text style={[styles.currentPrice, { color: colors.primary }]}>
            {formatPrice(price)}
          </Text>
          
          {originalPrice && originalPrice > price && (
            <Text style={[styles.originalPrice, { color: colors.textSecondary }]}>
              {formatPrice(originalPrice)}
            </Text>
          )}
        </View>
      </View>
    </CardWrapper>
  );
});

ProductCard.displayName = 'ProductCard';

const styles = StyleSheet.create({
  container: {
    width: '48%',
    marginHorizontal: '1%',
    marginBottom: 12,
    borderRadius: 12,
    overflow: 'hidden',
    elevation: 3, // Android阴影
    shadowColor: '#000', // iOS阴影
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
  },
  containerDark: {
    elevation: 5,
    shadowOpacity: 0.15,
  },
  image: {
    width: '100%',
    aspectRatio: 1,
  },
  infoContainer: {
    padding: 10,
  },
  title: {
    fontSize: 14,
    lineHeight: 20,
    fontWeight: '500',
    marginBottom: 6,
  },
  metaRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 8,
  },
  rating: {
    fontSize: 12,
  },
  sales: {
    fontSize: 11,
  },
  priceRow: {
    flexDirection: 'row',
    alignItems: 'baseline',
  },
  currentPrice: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  originalPrice: {
    fontSize: 12,
    textDecorationLine: 'line-through',
    marginLeft: 6,
  },
});

export default ProductCard;

/*
MonkeyCode生成的关键设计决策说明:

1. **平台差异化点击效果**
   - Android: android_ripple (原生水波纹)
   - iOS: opacity动画 (符合HIG规范)
   
2. **阴影处理**
   - Android: elevation属性
   - iOS: shadow*系列属性
   - 暗色模式下增强阴影对比度
   
3. **性能优化**
   - 使用memo避免不必要的重渲染
   - 设置displayName便于DevTools调试
   - 图片使用cachePolicy策略
   
4. **国际化友好**
   - 销量数字格式化(万为单位)
   - 价格分转元显示
*/

3.3 平台特定代码处理

// platformUtils.ts - MonkeyCode推荐的平台工具模块
import { Platform, StatusBar } from 'react-native';

/**
 * 平台检测与适配工具集
 * MonkeyCode提示: 将所有平台相关逻辑集中管理,
 *               避免散落在各处造成维护困难
 */

export const isIOS = Platform.OS === 'ios';
export const isAndroid = Platform.OS === 'android';

/** 安全区域顶部间距 */
export const safeAreaTop = () => {
  if (isIOS) {
    // iPhone X及以上需要额外间距
    const hasNotch = 
      Platform.Version as number >= 113 || // iOS 11+
      (Platform.isPad && (Platform.Version as number) >= 111);
    return hasNotch ? 44 : 20;
  }
  return StatusBar.currentHeight ?? 24; // Android状态栏高度
};

/** 底部安全区域 */
export const safeAreaBottom = () => {
  if (isIOS) {
    // iPhone X及以上底部Home Indicator
    return 34;
  }
  return 0; // Android导航栏通常覆盖内容
};

/** 获取字体大小(Android通常需要稍大) */
export function adaptiveFontSize(baseSize: number): number {
  if (isAndroid) {
    // Android字体渲染偏小,适当放大
    return baseSize * 1.05;
  }
  return baseSize;
}

/** 触摸反馈配置 */
export const touchFeedback = {
  activeOpacity: isIOS ? 0.7 : 1, // iOS用透明度
  rippleConfig: isAndroid ? {
    color: 'rgba(0,0,0,0.08)',
    borderless: false,
  } : undefined,
};

/** 平台特定的API请求头 */
export function getPlatformHeaders(): Record<string, string> {
  return {
    'X-Platform': Platform.OS,
    'X-OS-Version': String(Platform.Version),
    ...(!isIOS && { 'X-Device-Type': 'android' }),
  };
}

3.4 性能优化助手

// performance.tsx - MonkeyCode性能优化方案

import React, { useCallback, useMemo, useState, useEffect, useRef } from 'react';
import { FlatList, ListRenderItemInfo, ViewabilityConfig } from 'react-native';

/**
 * MonkeyCode性能优化最佳实践集合
 * 
 * 核心原则:
 * 1. 减少重渲染 (memo + useMemo + useCallback)
 * 2. 列表虚拟化 (FlatList正确使用)
 * 3. 图片优化 (懒加载 + 缓存 + 占位)
 * 4. 动画优化 (useNativeDriver)
 * 5. 内存管理 (及时清理资源)
 */

// ===== 1. 高性能列表组件 =====

interface OptimizedListProps<T> {
  data: T[];
  renderItem: (info: ListRenderItemInfo<T>) => React.ReactElement;
  keyExtractor: (item: T, index: number) => string;
  estimatedItemSize?: number;
  onEndReached?: () => void;
  headerComponent?: React.ReactElement;
  emptyComponent?: React.ReactElement;
}

export function OptimizedFlatList<T>({
  data,
  renderItem,
  keyExtractor,
  estimatedItemSize = 120,
  onEndReached,
  headerComponent,
  emptyComponent,
}: OptimizedListProps<T>) {
  
  // 可见性追踪 - 用于懒加载等场景
  const viewabilityConfig = useRef<ListabilityConfig>({
    itemVisiblePercentThreshold: 50,
    minimumViewTime: 300,
  }).current;

  const onViewableItemsChanged = useRef(({ changed }: any) => {
    changed.forEach((item: any) => {
      if (item.isViewable) {
        // Item进入可视区域时的回调
        console.log(`[Visible] ${item.key}`);
      }
    });
  }).current;

  return (
    <FlatList
      data={data}
      renderItem={renderItem}
      keyExtractor={keyExtractor}
      
      // MonkeyCode关键优化参数
      removeClippedSubviews={isAndroid} // Android裁剪不可见项
      maxToRenderPerBatch={10} // 每批渲染数量
      windowSize={21} // 视口前后渲染范围
      initialNumToRender={6} // 首次渲染数量
      updateCellsBatchingPeriod={50} // 批量更新间隔(ms)
      
      // 滚动性能
      scrollEventThrottle={16} // 60fps
      
      // 无限滚动
      onEndReached={onEndReached}
      onEndReachedThreshold={0.3}
      
      // 可见性追踪
      viewabilityConfig={viewabilityConfig}
      onViewableItemsChanged={onViewableItemsChanged}
      
      // 头部和空状态
      ListHeaderComponent={headerComponent}
      ListEmptyComponent={emptyComponent || <EmptyState />}
      
      // MonkeyCode建议: 固定item尺寸可大幅提升性能
      getItemLayout={estimatedItemSize ? (data, index) => ({
        length: estimatedItemSize,
        offset: estimatedItemSize * index,
        index,
      }) : undefined}
    />
  );
}

// ===== 2. 计算密集型操作优化 =====

/**
 * 使用Web Worker处理复杂计算
 * MonkeyCode提示: RN中可以使用react-native-workers或@aspect/react-native-worker
 */
export function useHeavyComputation<T>(
  computeFn: (...args: any[]) => T,
  deps: any[]
): { result: T | null; loading: boolean; error: Error | null } {
  const [result, setResult] = useState<T | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    setLoading(true);
    
    // 使用requestAnimationFrame避免阻塞UI
    requestAnimationFrame(() => {
      try {
        const start = performance.now();
        const computed = computeFn(...deps);
        const duration = performance.now() - start;
        
        // MonkeyCode警告: 如果计算超过100ms,考虑移到Worker
        if (duration > 100) {
          console.warn(
            `[Performance] Computation took ${duration.toFixed(0)}ms. ` +
            `Consider moving to a Web Worker.`
          );
        }
        
        setResult(computed);
      } catch (e) {
        setError(e instanceof Error ? e : new Error(String(e)));
      } finally {
        setLoading(false);
      }
    });
  }, deps);

  return { result, loading, error };
}

// ===== 3. 内存泄漏防护 =====

/**
 * 清理Hook - 用于订阅、定时器等需要手动清理的场景
 */
export function useCleanup(effect: () => (() => void) | void, deps?: any[]) {
  useEffect(() => {
    const cleanup = effect();
    return cleanup;
  }, deps);
}

/**
 * 防抖Hook - 适用于搜索输入等高频触发场景
 */
export function useDebounce<T>(value: T, delay: number = 300): T {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer); // 重要:清理定时器防止内存泄漏
  }, [value, delay]);

  return debouncedValue;
}

四、Flutter + MonkeyCode 实战

4.1 项目架构设计

# monkeycode_flutter_config.yaml
project:
  name: my_flutter_app
  description: "AI-powered Flutter application"
  
architecture:
  pattern: clean_architecture  # 推荐的架构模式
  state_management: riverpod   # 状态管理方案
  network: dio + retrofit     # 网络层
  local_database: hive + isar # 本地存储
  navigation: go_router       # 路由
  
features:
  - internationalization: true
  - dark_mode: true
  - analytics: firebase_analytics
  - crashlytics: true
  - push_notifications: firebase_messaging
  
quality:
  testing:
    unit: flutter_test
    widget: flutter_test
    integration: integration_test
  lint: very_good_analysis
  code_coverage_target: 80

4.2 Widget生成示例

// smart_list.dart - MonkeyCode生成的智能列表Widget
// 提示词: "创建一个支持下拉刷新、上拉加载更多、空状态展示、
//         错误重试的通用列表组件,支持多种布局模式"

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

/// 列表布局模式
enum ListLayoutMode {
  list,       // 列表模式
  grid,       // 网格模式
  waterfall,  // 瀑布流模式
}

/// MonkeyCode SmartList - 智能列表组件
/// 
/// 特性:
/// - 下拉刷新 (Pull-to-refresh)
/// - 上拉加载更多 (Load more)
/// - 空状态展示 (Empty state)
/// - 错误重试 (Error retry)
/// - 多种布局模式 (Multiple layout modes)
/// - 骨架屏 (Skeleton loading)
class SmartList<T> extends StatefulWidget {
  /// 数据源
  final Future<List<T>> Function(int page, int pageSize) fetchData;
  
  /// 每页数据量
  final int pageSize;
  
  /// Item构建器
  final Widget Function(T item, int index) itemBuilder;
  
  /// 布局模式
  final ListLayoutMode layoutMode;
  
  /// 网格列数 (grid模式时生效)
  final int crossAxisCount;
  
  /// 是否启用下拉刷新
  final bool enablePullRefresh;
  
  /// 是否启用上拉加载
  final bool enableLoadMore;
  
  /// 空状态Widget
  final Widget? emptyWidget;
  
  /// 错误Widget
  final Widget Function(Object error)? errorWidget;
  
  /// 分隔线
  final Widget? separatorBuilder;
  
  /// 内边距
  final EdgeInsetsGeometry? padding;
  
  /// 控制器 (用于外部控制)
  final SmartListController? controller;

  const SmartList({
    super.key,
    required this.fetchData,
    this.pageSize = 20,
    required this.itemBuilder,
    this.layoutMode = ListLayoutMode.list,
    this.crossAxisCount = 2,
    this.enablePullRefresh = true,
    this.enableLoadMore = true,
    this.emptyWidget,
    this.errorWidget,
    this.separatorBuilder,
    this.padding,
    this.controller,
  });

  @override
  State<SmartList<T>> createState() => _SmartListState<T>();
}

class _SmartListState<T> extends State<SmartList<T>> {
  late final SmartListController _controller =
      widget.controller ?? SmartListController();
  
  final List<T> _items = [];
  bool _isLoading = false;
  bool _hasMore = true;
  bool _isError = false;
  Object? _errorObj;
  int _currentPage = 0;
  
  @override
  void initState() {
    super.initState();
    _loadData(isRefresh: true);
  }
  
  Future<void> _loadData({required bool isRefresh}) async {
    if (_isLoading) return;
    
    setState(() {
      _isLoading = true;
      _isError = false;
      if (isRefresh) {
        _currentPage = 0;
        _hasMore = true;
      }
    });
    
    HapticFeedback.lightImpact(); // 触觉反馈
    
    try {
      final page = isRefresh ? 0 : _currentPage + 1;
      final newData = await widget.fetchData(page, widget.pageSize);
      
      if (!mounted) return;
      
      setState(() {
        if (isRefresh) {
          _items.clear();
          _items.addAll(newData);
        } else {
          _items.addAll(newData);
        }
        _currentPage = page;
        _hasMore = newData.length >= widget.pageSize;
        _isLoading = false;
      });
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _isError = true;
        _errorObj = e;
        _isLoading = false;
      });
    }
  }

  Widget _buildList() {
    switch (widget.layoutMode) {
      case ListLayoutMode.grid:
        return GridView.builder(
          padding: widget.padding,
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: widget.crossAxisCount,
            mainAxisSpacing: 8,
            crossAxisSpacing: 8,
            childAspectRatio: 0.75,
          ),
          itemCount: _items.length + (_hasMore ? 1 : 0),
          itemBuilder: (context, index) {
            if (index == _items.length) {
              return _buildLoadingMore();
            }
            return widget.itemBuilder(_items[index], index);
          },
        );
        
      case ListLayoutMode.waterfall:
        // 瀑布流需要使用staggered_grid_view包
        return _buildWaterfallList();
        
      case ListLayoutMode.list:
      default:
        return ListView.separated(
          padding: widget.padding,
          itemCount: _items.length + (_hasMore ? 1 : 0),
          separatorBuilder: (_, __) => 
              widget.separatorBuilder ?? const Divider(height: 1),
          itemBuilder: (context, index) {
            if (index == _items.length) {
              return _buildLoadingMore();
            }
            return widget.itemBuilder(_items[index], index);
          },
        );
    }
  }

  Widget _buildLoadingMore() {
    if (_isError) {
      return widget.errorWidget?.call(_errorObj!) ?? 
          ErrorRetryWidget(
            error: _errorObj!,
            onRetry: () => _loadData(isRefresh: false),
          );
    }
    
    if (!_hasMore && _items.isEmpty) {
      return widget.emptyWidget ?? const EmptyStateWidget();
    }
    
    if (!_hasMore) {
      return const Padding(
        padding: EdgeInsets.all(16),
        child: Center(
          child: Text('— 我是有底线的 —', style: TextStyle(color: Colors.grey)),
        ),
      );
    }
    
    return const Padding(
      padding: EdgeInsets.all(16),
      child: Center(child: CircularProgressIndicator()),
    );
  }

  @override
  Widget build(BuildContext context) {
    Widget content;
    
    if (_items.isEmpty && _isLoading) {
      content = const SkeletonLoading();
    } else if (_items.isEmpty && _isError) {
      content = widget.errorWidget?.call(_errorObj!) ??
          ErrorRetryWidget(error: _errorObj!, onRetry: () => _loadData(isRefresh: true));
    } else {
      content = widget.enablePullRefresh
          ? RefreshIndicator(
              onRefresh: () => _loadData(isRefresh: true),
              child: _buildList(),
            )
          : _buildList();
    }
    
    return AnimatedSwitcher(
      duration: const Duration(milliseconds: 300),
      child: content,
    );
  }
}

/// 外部控制器
class SmartListController {
  void refresh() {}
  void scrollToTop() {}
}

/// 空状态组件
class EmptyStateWidget extends StatelessWidget {
  const EmptyStateWidget({super.key});
  
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.inbox_outlined, size: 64, color: Colors.grey[400]),
          const SizedBox(height: 16),
          Text('暂无数据', style: TextStyle(fontSize: 16, color: Colors.grey[600])),
          const SizedBox(height: 8),
          Text('下拉刷新试试吧~', style: TextStyle(fontSize: 14, color: Colors.grey[400])),
        ],
      ),
    );
  }
}

/// 错误重试组件
class ErrorRetryWidget extends StatelessWidget {
  final Object error;
  final VoidCallback onRetry;
  
  const ErrorRetryWidget({super.key, required this.error, required this.onRetry});
  
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(32),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(Icons.error_outline, size: 48, color: Colors.red[300]),
            const SizedBox(height: 16),
            Text('出错了: $error', textAlign: TextAlign.center,
                style: TextStyle(color: Colors.grey[600])),
            const SizedBox(height: 16),
            Elevated.icon(
              onPressed: onRetry,
              icon: const Icon(Icons.refresh),
              label: const Text('点击重试'),
            ),
          ],
        ),
      ),
    );
  }
}

/// 骨架屏组件
class SkeletonLoading extends StatelessWidget {
  const SkeletonLoading({super.key});
  
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: 6,
      itemBuilder: (context, index) => Padding(
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
        child: Container(
          height: 120,
          decoration: BoxDecoration(
            color: Colors.grey[200],
            borderRadius: BorderRadius.circular(8),
          ),
        ),
      ),
    );
  }
}

4.3 平台通道与原生交互

// native_bridge.dart - MonkeyCode生成的原生桥接模块
// 提示词: "创建一个统一的原生功能调用接口,包括:
//         相机拍照、相册选择、文件存储、分享功能、
//         设备信息获取、权限管理"

import 'dart:io' show Platform;
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/services.dart';

/// 统一的原生功能桥接
/// MonkeyCode设计原则: 所有原生调用通过此中心化入口
class NativeBridge {
  static const MethodChannel _channel = MethodChannel('com.app/native');
  
  static const EventChannel _eventChannel = EventChannel('com.app/events');

  // ========== 相机 & 相册 ==========
  
  /// 打开相机拍照
  static Future<MediaResult?> takePhoto({
    bool allowEdit = false,
    double? maxWidth,
    double? maxHeight,
    int quality = 85,
  }) async {
    try {
      final result = await _channel.invokeMethod<Map>('takePhoto', {
        'allowEdit': allowEdit,
        'maxWidth': maxWidth,
        'maxHeight': maxHeight,
        'quality': quality,
      });
      return result != null ? MediaResult.fromMap(result) : null;
    } on PlatformException catch (e) {
      debugPrint('[NativeBridge] takePhoto error: $e');
      return null;
    }
  }

  /// 从相册选择图片
  static Future<List<MediaResult>?> pickImages({
    int maxCount = 9,
    bool enableCamera = true,
  }) async {
    try {
      final result = await _channel.invokeMethod<List<dynamic>>(
        'pickImages', {'maxCount': maxCount, 'enableCamera': enableCamera},
      );
      return result?.map((e) => MediaResult.fromMap(Map<String, dynamic>.from(e))).toList();
    } on PlatformException catch (e) {
      debugPrint('[NativeBridge] pickImages error: $e');
      return null;
    }
  }

  // ========== 文件系统 ==========
  
  /// 保存文件到本地
  static Future<String?> saveFile({
    required Uint8List bytes,
    required String fileName,
    String? directory,
  }) async {
    try {
      return await _channel.invokeMethod<String>('saveFile', {
        'bytes': bytes,
        'fileName': fileName,
        'directory': directory,
      });
    } on PlatformException catch (e) {
      debugPrint('[NativeBridge] saveFile error: $e');
      return null;
    }
  }

  /// 获取临时目录路径
  static Future<String> get tempPath async {
    return await _channel.invokeMethod<String>('getTempPath') ?? '';
  }

  // ========== 分享功能 ==========
  
  /// 分享内容
  static Future<bool> share({
    String? text,
    String? subject,
    List<String>? filePaths,
  }) async {
    try {
      return await _channel.invokeMethod<bool>('share', {
        'text': text,
        'subject': subject,
        'filePaths': filePaths,
      }) ?? false;
    } on PlatformException catch (e) {
      debugPrint('[NativeBridge] share error: $e');
      return false;
    }
  }

  // ========== 设备信息 ==========
  
  /// 获取设备信息
  static Future<DeviceInfo> getDeviceInfo() async {
    try {
      final map = await _channel.invokeMethod<Map>('getDeviceInfo') ?? {};
      return DeviceInfo.fromMap(Map<String, dynamic>.from(map));
    } on PlatformException catch (e) {
      debugPrint('[NativeBridge] getDeviceInfo error: $e');
      return DeviceInfo.empty();
    }
  }

  // ========== 权限管理 ==========
  
  /// 请求权限
  static Future<PermissionStatus> requestPermission(PermissionType type) async {
    try {
      final status = await _channel.invokeMethod<int>('requestPermission', {
        'type': type.index,
      });
      return PermissionStatus.values[status ?? 0];
    } on PlatformException catch (e) {
      debugPrint('[NativeBridge] requestPermission error: $e');
      return PermissionStatus.denied;
    }
  }

  // ========== 事件监听 ==========
  
  /// 监听App生命周期事件
  static Stream<AppLifecycleState> get appLifecycleStream {
    return _eventChannel.receiveBroadcastStream().map((event) {
      switch (event) {
        case 'resume': return AppLifecycleState.resumed;
        case 'pause': return AppLifecycleState.paused;
        case 'inactive': return AppLifecycleState.inactive;
        default: return AppLifecycleState.resumed;
      }
    });
  }
}

/// 媒体结果
class MediaResult {
  final String path;
  final String? thumbnailPath;
  final int width;
  final int height;
  final int size; // bytes
  final String mimeType;

  const MediaResult({
    required this.path,
    this.thumbnailPath,
    required this.width,
    required this.height,
    required this.size,
    required this.mimeType,
  });

  factory MediaResult.fromMap(Map<String, dynamic> map) => MediaResult(
    path: map['path'] ?? '',
    thumbnailPath: map['thumbnailPath'],
    width: map['width'] ?? 0,
    height: map['height'] ?? 0,
    size: map['size'] ?? 0,
    mimeType: map['mimeType'] ?? '',
  );

  double get aspectRatio => height > 0 ? width / height : 1.0;
  String get sizeFormatted {
    if (size < 1024) return '$size B';
    if (size < 1024 * 1024) return '${(size / 1024).toStringAsFixed(1)} KB';
    return '${(size / (1024 * 1024)).toStringAsFixed(1)} MB';
  }
}

/// 设备信息
class DeviceInfo {
  final String brand;
  final String model;
  final String osVersion;
  final String appVersion;
  final int sdkVersion;
  final String deviceId;
  final double screenWidth;
  final double screenHeight;
  final double pixelRatio;

  const DeviceInfo({
    required this.brand,
    required this.model,
    required this.osVersion,
    required this.appVersion,
    required this.sdkVersion,
    required this.deviceId,
    required this.screenWidth,
    required this.screenHeight,
    required this.pixelRatio,
  });

  factory DeviceInfo.fromMap(Map<String, dynamic> map) => DeviceInfo(
    brand: map['brand'] ?? '',
    model: map['model'] ?? '',
    osVersion: map['osVersion'] ?? '',
    appVersion: map['appVersion'] ?? '',
    sdkVersion: map['sdkVersion'] ?? 0,
    deviceId: map['deviceId'] ?? '',
    screenWidth: (map['screenWidth'] ?? 0).toDouble(),
    screenHeight: (map['screenHeight'] ?? 0).toDouble(),
    pixelRatio: (map['pixelRatio'] ?? 2).toDouble(),
  );

  factory DeviceInfo.empty() => DeviceInfo(
    brand: '', model: '', osVersion: '', appVersion: '',
    sdkVersion: 0, deviceId: '', 
    screenWidth: 0, screenHeight: 0, pixelRatio: 2,
  );

  bool get isTablet => screenWidth >= 768;
  String get deviceName => '$brand $model';
}

/// 权限类型
enum PermissionType { camera, photo, location, microphone, notification, storage }

/// 权限状态
enum PermissionStatus { granted, denied, permanentlyDenied, restricted }

五、Uni-app/Taro + MonkeyCode 多端发布

5.1 条件编译自动化

// monkeycode-platform.js - MonkeyCode多端条件编译工具
/**
 * 自动处理不同平台的条件编译代码
 * 支持: #ifdef / #ifndef / #endif 语法
 */

const PLATFORMS = {
  H5: 'h5',
  'APP-PLUS': 'app',
  'MP-WEIXIN': 'mp-weixin',
  'MP-ALIPAY': 'mp-alipay',
  'MP-BAIDU': 'mp-baidu',
  'MP-TOUTIAO': 'mp-toutiao',
  'MP-QQ': 'mp-qq',
};

/**
 * 解析条件编译块
 * @param {string} source - 源代码
 * @param {string} targetPlatform - 目标平台
 * @returns {string} 处理后的代码
 */
function processConditionalCompilation(source, targetPlatform) {
  const lines = source.split('\n');
  const output = [];
  let skipStack = []; // 嵌套的条件编译栈
  
  for (let i = 0; i < lines.length; i++) {
    const line = lines[i];
    const trimmed = line.trim();
    
    // 检测 #ifdef
    const ifdefMatch = trimmed.match(/^\/\/\s*#ifdef\s+(.+)$/);
    if (ifdefMatch) {
      const platforms = ifdefMatch[1].split(/\s+/);
      const shouldInclude = platforms.includes(targetPlatform) || 
                            platforms.includes('ALL');
      skipStack.push(!shouldInclude);
      continue;
    }
    
    // 检测 #ifndef
    const ifndefMatch = trimmed.match(/^\/\/\s*#ifndef\s+(.+)$/);
    if (ifndefMatch) {
      const platforms = ifndefMatch[1].split(/\s+/);
      const shouldExclude = platforms.includes(targetPlatform);
      skipStack.push(shouldExclude);
      continue;
    }
    
    // 检测 #endif
    if (trimmed.startsWith('// #endif')) {
      if (skipStack.length > 0) {
        skipStack.pop();
      }
      continue;
    }
    
    // 判断是否应该包含当前行
    const shouldSkip = skipStack.some(skip => skip);
    if (!shouldSkip) {
      output.push(line);
    }
  }
  
  return output.join('\n');
}

// 示例: 处理前
const beforeProcess = `
// 通用代码
console.log('Hello from all platforms!');

// #ifdef MP-WEIXIN
wx.login({ success: (res) => console.log(res.code) });
// #endif

// #ifdef APP-PLUS
plus.runtime.getProperty(plus.runtime.appid, (info) => console.log(info));
// #endif

// #ifdef H5
localStorage.setItem('token', 'xxx');
// #endif
`;

// 处理后 (目标: MP-WEIXIN)
const afterWeixin = processConditionalCompilation(beforeProcess, 'mp-weixin');
console.log(afterWeixin);
// 输出:
// 通用代码
// console.log('Hello from all platforms!');
// wx.login({ success: (res) => console.log(res.code) });

module.exports = { processConditionalCompilation, PLATFORMS };

5.2 多端API适配层

// apiAdapter.ts - MonkeyCode生成的多端API适配器
// 提示词: "创建一个统一的API适配层,封装网络请求、
//         存储、路由跳转、分享等能力的多端差异"

type Platform = 'h5' | 'weixin' | 'alipay' | 'app' | 'toutiao' | 'qq';

/** 获取当前运行环境 */
function getPlatform(): Platform {
  // #ifdef MP-WEIXIN
  return 'weixin';
  // #endif
  // #ifdef MP-ALIPAY
  return 'alipay';
  // #endif
  // #ifdef MP-TOUTIAO
  return 'toutiao';
  // #endif
  // #ifdef MP-QQ
  return 'qq';
  // #endif
  // #ifdef APP-PLUS
  return 'app';
  // #endif
  // #ifdef H5
  return 'h5';
  // #endif
  return 'h5';
}

// ========== 网络请求适配 ==========

interface RequestOptions {
  url: string;
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
  data?: any;
  header?: Record<string, string>;
  timeout?: number;
}

interface Response<T = any> {
  data: T;
  statusCode: number;
  header: Record<string, string>;
}

function request<T = any>(options: RequestOptions): Promise<Response<T>> {
  const platform = getPlatform();
  
  // #ifdef MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-QQ
  return new Promise((resolve, reject) => {
    uni.request({
      url: options.url,
      method: options.method || 'GET',
      data: options.data,
      header: {
        'Content-Type': 'application/json',
        ...options.header,
      },
      timeout: options.timeout || 15000,
      success: (res: any) => resolve(res),
      fail: (err: any) => reject(err),
    });
  });
  // #endif
  
  // #ifdef APP-PLUS
  // App端可以使用更强大的请求库
  return new Promise((resolve, reject) => {
    uni.request({
      ...options,
      sslVerify: true, // MonkeyCode建议: 生产环境开启SSL验证
      success: (res: any) => resolve(res),
      fail: (err: any) => reject(err),
    });
  });
  // #endif
  
  // #ifdef H5
  // H5环境直接使用fetch
  return fetch(options.url, {
    method: options.method || 'GET',
    headers: options.header,
    body: options.data ? JSON.stringify(options.data) : undefined,
    signal: AbortSignal.timeout(options.timeout || 15000),
  }).then(async (res) => ({
    data: await res.json(),
    statusCode: res.status,
    header: Object.fromEntries(res.headers.entries()),
  }));
  // #endif
}

// ========== 存储适配 ==========

const storage = {
  set(key: string, value: any): void {
    const data = JSON.stringify(value);
    // #ifdef MP-WEIXIN || MP-ALIPAY || APP-PLUS
    uni.setStorageSync(key, data);
    // #endif
    // #ifdef H5
    localStorage.setItem(key, data);
    // #endif
  },
  
  get<T = any>(key: string): T | null {
    // #ifdef MP-WEIXIN || MP-ALIPAY || APP-PLUS
    const data = uni.getStorageSync(key);
    // #endif
    // #ifdef H5
    const data = localStorage.getItem(key);
    // #endif
    
    if (data) {
      try {
        return JSON.parse(data);
      } catch {
        return null;
      }
    }
    return null;
  },
  
  remove(key: string): void {
    // #ifdef MP-WEIXIN || MP-ALIPAY || APP-PLUS
    uni.removeStorageSync(key);
    // #endif
    // #ifdef H5
    localStorage.removeItem(key);
    // #endif
  },
  
  clear(): void {
    // #ifdef MP-WEIXIN || MP-ALIPAY || APP-PLUS
    uni.clearStorageSync();
    // #endif
    // #ifdef H5
    localStorage.clear();
    // #endif
  }
};

// ========== 路由适配 ==========

const router = {
  push(url: string, params?: Record<string, any>): void {
    // MonkeyCode注意: 不同平台URL格式可能不同
    let finalUrl = url;
    
    // #ifdef MP-WEIXIN
    if (params) {
      const query = Object.entries(params)
        .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
        .join('&');
      finalUrl += (url.includes('?') ? '&' : '?') + query;
    }
    uni.navigateTo({ url: finalUrl });
    // #endif
    
    // #ifdef H5
    // H5使用Vue Router或其他路由方案
    if (params) {
      // 假设使用Vue Router
      // router.push({ path: url, query: params });
    }
    // #endif
  },
  
  back(delta: number = 1): void {
    uni.navigateBack({ delta });
  },
  
  reLaunch(url: string): void {
    uni.reLaunch({ url });
  },
  
  switchTab(url: string): void {
    uni.switchTab({ url });
  }
};

// ========== 分享适配 ==========

const share = {
  /** 设置分享信息 */
  config(options: {
    title: string;
    path: string;
    imageUrl?: string;
    desc?: string;
  }): void {
    // #ifdef MP-WEIXIN
    wx.showShareMenu({
      withShareTicket: true,
      menus: ['shareAppMessage', 'shareTimeline'],
    });
    // #endif
    
    // #ifdef MP-WEIXIN
    // 微信小程序分享
    (wx as any).onAppMessage?.(() => ({
      title: options.title,
      path: options.path,
      imageUrl: options.imageUrl,
    }));
    // #endif
    
    // #ifdef APP-PLUS
    // App端分享需要调用原生分享
    plus.share.sendWithSystem?.({
      type: 'web',
      href: options.path,
    });
    // #endif
  },
  
  /** 主动调起分享面板 */
  showPanel(options: {
    title: string;
    summary?: string;
    imageUrl?: string;
  }): void {
    // #ifdef MP-WEIXIN || MP-ALIPAY
    // 小程序只能被动分享,不支持主动调起
    uni.showToast({ title: '请点击右上角分享', icon: 'none' });
    // #endif
    
    // #ifdef APP-PLUS
    plus.share.sendWithSystem?.({
      type: 'text',
      content: options.summary || options.title,
    });
    // #endif
  }
};

// ========== 导出统一接口 ==========
export {
  getPlatform,
  type Platform,
  request,
  storage,
  router,
  share,
};

六、性能优化专题

6.1 MonkeyCode性能诊断清单

┌─────────────────────────────────────────────────────────────┐
│           MonkeyCode 移动端性能诊断清单                     │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  📱 启动性能                                                │
│  ├─ [ ] 冷启动时间 < 3秒                                    │
│  ├─ [ ] 首屏渲染时间 < 1.5秒                                │
│  ├─ [ ] 避免在启动时执行耗时操作                             │
│  ├─ [ ] 使用启动屏骨架/占位图                               │
│  └─ [ ] 延迟加载非首屏必要模块                              │
│                                                             │
│  🎨 渲染性能                                                │
│  ├─ [ ] FPS稳定在55-60                                     │
│  ├─ [ ] 长列表使用虚拟列表(Flutter/Native)                  │
│  ├─ [ ] 避免过度嵌套的视图层级                              │
│  ├─ [ ] 图片使用合适尺寸和格式                              │
│  ├─ [ ] 动画使用GPU加速(useNativeDriver)                   │
│  └─ [ ] 避免在滚动视图中执行同步操作                        │
│                                                             │
│  💾 内存管理                                                │
│  ├─ [ ] 内存占用 < 300MB (iOS) / < 400MB (Android)         │
│  ├─ [ ] 及时释放大对象和图片缓存                            │
│  ├─ [ ] 避免内存泄漏(闭包/订阅/定时器)                     │
│  ├─ [ ] 使用WeakReference持有不必要强引用                   │
│  └─ [ ] 合理设置缓存大小上限                               │
│                                                             │
│  🔌 网络性能                                                │
│  ├─ [ ] 接口响应时间 P95 < 2秒                              │
│  ├─ [ ] 启用HTTP/2和gzip压缩                               │
│  ├─ [ ] 合并小请求,减少RTT                                │
│  ├─ [ ] 图片使用CDN和渐进式加载                            │
│  ├─ [ ] 实现合理的缓存策略                                 │
│  └─ [ ] 离线优先,后台静默更新                             │
│                                                             │
│  🔋 电量/流量                                              │
│  ├─ [ ] 后台任务最小化                                     │
│  ├─ [ ] 定位/GPS按需开启                                   │
│  ├─ [ ] 减少不必要的唤醒                                   │
│  ├─ [ ] 批量上传/下载                                      │
│  └─ [ ] WiFi下预加载资源                                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

6.2 MonkeyCode自动生成的性能监控代码

// performanceMonitor.ts - MonkeyCode性能监控SDK
// 提示词: "创建一个轻量级的移动端性能监控模块,
//         监控FPS、内存、网络请求、页面加载时间、
//         卡顿率,支持上报到监控系统"

interface MetricData {
  name: string;
  value: number;
  timestamp: number;
  tags?: Record<string, string>;
}

interface PerformanceReport {
  sessionId: string;
  userId?: string;
  page: string;
  platform: string;
  metrics: MetricData[];
  startTime: number;
  endTime: number;
}

/**
 * MonkeyCode Performance Monitor
 * 
 * 功能:
 * - FPS实时监控
 * - 内存使用追踪
 * - 网络请求记录
 * - 页面加载计时
 * - 卡顿检测
 * - 异常捕获
 * - 数据上报
 */
class PerfMonitor {
  private metrics: MetricData[] = [];
  private frameTimestamps: number[] = [];
  private fpsCallbackId: number | null = null;
  private sessionId: string;
  private reportUrl: string;
  private enabled: boolean = true;
  private batchTimer: ReturnType<typeof setTimeout> | null = null;

  constructor(config: { reportUrl: string; enabled?: boolean }) {
    this.sessionId = this.generateSessionId();
    this.reportUrl = config.reportUrl;
    this.enabled = config.enabled !== false;
    
    if (this.enabled) {
      this.startMonitoring();
    }
  }

  // ===== 会话管理 =====
  private generateSessionId(): string {
    return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }

  // ===== FPS监控 =====
  private startFPSMonitoring() {
    const trackFrame = () => {
      this.frameTimestamps.push(performance.now());
      
      // 只保留最近60帧的时间戳
      if (this.frameTimestamps.length > 60) {
        this.frameTimestamps.shift();
      }
      
      // 每秒计算一次FPS
      if (this.frameTimestamps.length >= 2) {
        const now = performance.now();
        const oneSecondAgo = now - 1000;
        const framesInLastSecond = this.frameTimestamps.filter(
          t => t >= oneSecondAgo
        ).length;
        
        this.recordMetric('fps', framesInLastSecond);
        
        // MonkeyCode: FPS低于30时标记为卡顿
        if (framesInLastSecond < 30) {
          this.recordMetric('jank_count', 1, { severity: 'high' });
        }
      }
      
      this.fpsCallbackId = requestAnimationFrame(trackFrame);
    };
    
    this.fpsCallbackId = requestAnimationFrame(trackFrame);
  }

  // ===== 内存监控 (仅部分平台支持) =====
  private startMemoryMonitor() {
    if ('memory' in performance) {
      setInterval(() => {
        const mem = (performance as any).memory;
        this.recordMetric('js_heap_size', mem.usedJSHeapSize);
        this.recordMetric('js_heap_limit', mem.jsHeapSizeLimit);
        
        // MonkeyCode警告: 内存使用超过80%阈值
        if (mem.usedJSHeapSize / mem.jsHeapSizeLimit > 0.8) {
          this.recordMetric('memory_warning', 1, {
            usage_percent: ((mem.usedJSHeapSize / mem.jsHeapSizeLimit) * 100).toFixed(1),
          });
        }
      }, 5000);
    }
  }

  // ===== 网络请求拦截 =====
  interceptNetworkRequests() {
    const originalFetch = window.fetch.bind(window);
    window.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
      const startTime = performance.now();
      const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
      
      try {
        const response = await originalFetch(input, init);
        const duration = performance.now() - startTime;
        
        this.recordMetric('network_request_duration', Math.round(duration), {
          url: this.sanitizeUrl(url),
          method: init?.method || 'GET',
          status: response.status.toString(),
          success: (response.status < 400).toString(),
        });
        
        return response;
      } catch (error) {
        const duration = performance.now() - startTime;
        this.recordMetric('network_request_error', 1, {
          url: this.sanitizeUrl(url),
          duration_ms: Math.round(duration).toString(),
        });
        throw error;
      }
    };
  }

  // ===== 页面加载计时 =====
  markPageLoad(pageName: string) {
    // MonkeyCode: 使用Performance API精确测量
    if ('performance' in window && 'getEntriesByType' in performance) {
      const navEntry = performance.getEntriesByType('navigation')[0];
      if (navEntry) {
        this.recordMetric('page_load_dom_complete', Math.round(navEntry.domComplete), { page: pageName });
        this.recordMetric('page_load_fcp', Math.round(navEntry.responseStart - navEntry.requestStart), { page: pageName });
        this.recordMetric('page_load_tti', Math.round(navEntry.domInteractive - navEntry.requestStart), { page: pageName });
      }
    }
  }

  // ===== 自定义指标记录 =====
  recordMetric(name: string, value: number, tags?: Record<string, string>) {
    if (!this.enabled) return;
    
    this.metrics.push({
      name,
      value,
      timestamp: Date.now(),
      tags,
    });
    
    // 达到一定数量后批量上报
    if (this.metrics.length >= 20) {
      this.flush();
    } else if (!this.batchTimer) {
      this.batchTimer = setTimeout(() => this.flush(), 10000);
    }
  }

  // ===== 手动上报 =====
  async flush() {
    if (this.batchTimer) {
      clearTimeout(this.batchTimer);
      this.batchTimer = null;
    }
    
    if (this.metrics.length === 0) return;
    
    const report: PerformanceReport = {
      sessionId: this.sessionId,
      page: location.pathname,
      platform: this.detectPlatform(),
      metrics: [...this.metrics],
      startTime: this.metrics[0]?.timestamp || Date.now(),
      endTime: Date.now(),
    };
    
    this.metrics = [];
    
    // 使用sendBeacon确保数据可靠发送
    if (navigator.sendBeacon) {
      navigator.sendBeacon(this.reportUrl, JSON.stringify(report));
    } else {
      // Fallback: 使用fetch keepalive
      fetch(this.reportUrl, {
        method: 'POST',
        body: JSON.stringify(report),
        headers: { 'Content-Type': 'application/json' },
        keepalive: true,
      }).catch(() => {}); // 上报失败不影响用户体验
    }
  }

  // ===== 工具方法 =====
  private sanitizeUrl(url: string): string {
    try {
      const u = new URL(url);
      // 移除敏感参数
      u.searchParams.delete('token');
      u.searchParams.delete('session_id');
      return `${u.origin}${u.pathname}`;
    } catch {
      return url.split('?')[0];
    }
  }

  private detectPlatform(): string {
    const ua = navigator.userAgent.toLowerCase();
    if (ua.includes('miniprogram')) return 'mini-program';
    if (ua.includes('android')) return 'android';
    if (ua.includes('iphone') || ua.includes('ipad')) return 'ios';
    return 'unknown';
  }

  // ===== 生命周期 =====
  private startMonitoring() {
    this.startFPSMonitoring();
    this.startMemoryMonitor();
    this.interceptNetworkRequests();
    
    // 页面卸载时上报剩余数据
    window.addEventListener('beforeunload', () => this.flush());
    // 页面隐藏时也上报
    document.addEventListener('visibilitychange', () => {
      if (document.hidden) this.flush();
    });
  }

  destroy() {
    this.enabled = false;
    if (this.fpsCallbackId) {
      cancelAnimationFrame(this.fpsCallbackId);
    }
    this.flush();
  }
}

// ===== 使用示例 =====
// const monitor = new PerfMonitor({
//   reportUrl: 'https://analytics.example.com/perf',
//   enabled: true,
// });

// // 记录自定义指标
// monitor.recordMetric('button_click_time', 150, { button: 'submit_order' });

// // 页面加载完成时调用
// monitor.markPageLoad('home');

export { PerfMonitor };
export type { MetricData, PerformanceReport };

七、真实案例:电商App跨平台重构

7.1 项目背景

维度 详情
项目名称 某电商平台App重构
原技术栈 iOS原生(Swift) + Android原生(Kotlin)
新技术栈 React Native + MonkeyCode
团队规模 15人 (iOS 5人 + Android 5人 + RN 5人)
项目周期 6个月
代码量 约20万行

7.2 MonkeyCode参与的重构流程

Phase 1: 评估与分析 (2周)
├── MonkeyCode分析现有原生代码
├── 识别可复用的业务逻辑 (~60%)
├── 评估迁移风险和依赖关系
└── 输出迁移报告和优先级排序

Phase 2: 基础设施搭建 (3周)
├── MonkeyCode生成项目脚手架
├── 创建统一的组件库
├── 配置多环境(Dev/Staging/Prod)
└── 搭建CI/CD流水线

Phase 3: 核心模块迁移 (8周)
├── 用户认证模块
├── 商品浏览/搜索模块
├── 购物车模块
├── 订单流程模块
└── 支付模块

Phase 4: 业务功能迁移 (6周)
├── 个人中心
├── 消息通知
├── 优惠券/活动
├── 客服系统
└── 其他辅助功能

Phase 5: 优化与上线 (4周)
├── 性能优化 (MonkeyCode诊断)
├── 兼容性测试
├── 灰度发布
└── 全量上线

7.3 重构成果

指标 重构前 重构后 变化
代码总量 ~25万行(iOS+Android) ~12万行(RN) -52%
开发效率 基准值 提升2.3倍 +130%
Bug修复速度 平均2天/个 平均4小时/个 -83%
发版周期 双周发版 支持热更新 灵活
包体积(iOS) 85MB 35MB(RN bundle) -59%
包体积(Android) 65MB 28MB(RN bundle) -57%
启动时间(iOS) 2.8s 1.9s -32%
启动时间(Android) 3.2s 2.1s -34%
Crash率(iOS) 0.8% 0.3% -62%
Crash率(Android) 1.2% 0.4% -67%
团队人数 15人 10人(-33%) -33%

7.4 经验总结

✅ 成功经验:

  1. 渐进式迁移 — 不要一次性全部重写,先从非核心页面开始验证
  2. 保持双版本并行 — 新旧版本同时维护一段时间,确保回退能力
  3. 充分利用MonkeyCode — 代码转换、测试生成、文档编写都能大幅提效
  4. 建立组件先行策略 — 先把基础组件做好,业务页面组装会很快
  5. 重视性能基线 — 迁移前后都要做性能基准测试

⚠️ 注意事项:

  1. 原生模块仍需保留 — 不是所有功能都能100%跨平台,合理保留原生模块
  2. 团队技能转型 — 给团队足够的学习和适应时间
  3. 测试覆盖率不能降 — 跨平台意味着更多的边界情况
  4. 监控体系要跟上 — 新架构需要有新的监控指标

八、常见问题FAQ

Q1: MonkeyCode能完全替代手工写代码吗?

A: 不能也不应该。MonkeyCode是"副驾驶",不是"自动驾驶"。它最适合:

  • 重复性的模板代码
  • 熟悉模式的变体实现
  • 初稿和原型开发
  • 代码审查和学习参考

复杂的业务逻辑、创新的UI交互、性能关键的底层代码仍然需要人工把控。

Q2: 哪种跨平台框架最适合配合MonkeyCode?

A: 取决于你的场景:

场景 推荐框架 MonkeyCode配合度
快速MVP/原型 Uni-app ⭐⭐⭐⭐⭐
追求极致性能 Flutter ⭐⭐⭐⭐⭐
Web技术栈团队 React Native ⭐⭐⭐⭐⭐
多小程序分发 Taro ⭐⭐⭐⭐
简单H5增强 Capacitor ⭐⭐⭐⭐

Q3: 如何处理MonkeyCode生成的代码不符合项目规范?

A: 几种方法:

  1. 定制Prompt模板 — 在项目中建立MonkeyCode使用的标准prompt模板
  2. ESLint/Prettier规则 — 用代码格式化工具强制统一风格
  3. Code Review流程 — AI生成的代码同样需要人工审核
  4. 持续迭代 — 把修正后的代码喂给MonkeyCode,它会学习改进

Q4: 跨平台开发的性能真的能达到原生水平吗?

A: 对于绝大多数应用场景,现代跨平台框架的性能已经非常接近原生。根据我们的实测数据:

  • UI流畅度: Flutter ≈ 原生 > RN > Uni-app
  • 启动速度: 原生 > Flutter > RN > Uni-app
  • 包体大小: Uni-app < RN < Flutter < 原生
  • 开发效率: Uni-app ≈ Flutter > RN > 原生

选择时需要在性能、效率和生态之间做权衡。


九、未来展望

9.1 MonkeyCode跨平台路线图

2026 Q3 (当前):
├── ✅ React Native完整支持
├── ✅ Flutter完整支持
├── ✅ Uni-app/Taro支持
└── ✅ 基础性能优化工具

2026 Q4:
├── 🔨 原生代码→跨平台代码自动转换
├── 🔨 多框架互转 (RN↔Flutter↔Uni)
├── 🔨 设计稿(Figma/Sketch)→代码
└── 🔨 自动化E2E测试生成

2027 Q1:
├── 📋 AR/VR跨平台支持
├── 📋 Desktop跨平台(Electron/Tauri)
├── 📋 IoT嵌入式设备支持
└── 📋 实时协作编程

2027 Q2+:
├── 🚀 全平台统一抽象层
├── 🚀 AI驱动的设计系统
├── 🚀 自然语言→完整App
└── 🚀 低代码/无代码平台集成

9.2 我们的愿景

"我们相信,未来的软件开发不应该被平台所束缚。每一个伟大的想法,都应该能够触达每一个用户——无论他们使用什么设备。MonkeyCode正在让这个愿景成为现实。"


结语

跨平台开发已经从"能用"走向了"好用"的阶段。而MonkeyCode的出现,正在将这个阶段推向"好用且高效"的新高度。

通过本文的介绍,你应该已经了解了:

  • 🎯 各主流跨平台框架的特点和适用场景
  • 🛠️ 如何使用MonkeyCode高效开发跨平台应用
  • ⚡ 性能优化的核心方法和工具
  • 📊 真实项目的重构经验和数据
  • 🔮 未来发展的方向和可能性

下一步行动建议:

  1. 🆓 下载安装MonkeyCode,体验跨平台开发
  2. 📖 选择一个框架深入学习(推荐从Uni-app或Flutter开始)
  3. 💡 尝试用自然语言描述你想要的功能,看看MonkeyCode能生成什么
  4. 🤝 加入社区,分享你的跨平台开发经验

记住:最好的学习方式就是动手实践。打开MonkeyCode,开始你的第一个跨平台项目吧!


本文最后更新:2026年7月16日
作者:MonkeyCode团队

相关阅读:

下一篇预告:[MonkeyCode代码审查功能深度解析]

posted on 2026-07-16 18:12  MonkeyCode  阅读(13)  评论(0)    收藏  举报