高级主题 #

性能优化 #

性能优化概述 #

text
┌─────────────────────────────────────────────────────────────┐
│                    性能优化要点                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ├── 启动性能                                               │
│  │   - 延迟初始化                                          │
│  │   - AOT 编译                                            │
│  │   - 资源优化                                            │
│  │                                                         │
│  ├── 运行时性能                                             │
│  │   - UI 渲染优化                                         │
│  │   - 数据绑定优化                                        │
│  │   - 内存管理                                            │
│  │                                                         │
│  ├── 网络性能                                               │
│  │   - 异步操作                                            │
│  │   - 缓存策略                                            │
│  │   - 数据压缩                                            │
│  │                                                         │
│  └── 应用体积                                               │
│      - 链接器配置                                          │
│      - 资源压缩                                            │
│      - 程序集裁剪                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

启动优化 #

延迟初始化 #

csharp
public partial class App : Application
{
    public App()
    {
        InitializeComponent();
        
        MainPage = new LoadingPage();
    }

    protected override async void OnStart()
    {
        await InitializeServicesAsync();
        MainPage = new AppShell();
    }

    private async Task InitializeServicesAsync()
    {
        var tasks = new List<Task>
        {
            InitializeDatabaseAsync(),
            InitializeCacheAsync(),
            LoadUserSettingsAsync()
        };
        
        await Task.WhenAll(tasks);
    }
}

XAML 编译 #

csharp
using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace MyApp
{
}

UI 渲染优化 #

使用 Compiled Bindings #

xml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.MainPage"
             x:DataType="local:MainViewModel">
    
    <Label Text="{Binding Title}" />
    
</ContentPage>

避免过度布局 #

xml
<Grid RowDefinitions="Auto, *, Auto">
    <Label Grid.Row="0" Text="标题" />
    <ScrollView Grid.Row="1">
        <StackLayout>
        </StackLayout>
    </ScrollView>
    <Button Grid.Row="2" Text="提交" />
</Grid>

使用 CollectionView 替代 ListView #

xml
<CollectionView ItemsSource="{Binding Items}">
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType="local:Item">
            <StackLayout>
                <Label Text="{Binding Title}" />
            </StackLayout>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

数据绑定优化 #

使用 Compiled Bindings #

csharp
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        BindingContext = new MainViewModel();
    }
}

避免频繁更新 #

csharp
public class MainViewModel : ViewModelBase
{
    private CancellationTokenSource _cts;

    private string _searchText;
    public string SearchText
    {
        get => _searchText;
        set
        {
            SetProperty(ref _searchText, value);
            DebounceSearch(value);
        }
    }

    private void DebounceSearch(string text)
    {
        _cts?.Cancel();
        _cts = new CancellationTokenSource();
        
        Task.Delay(500, _cts.Token)
            .ContinueWith(t =>
            {
                if (!t.IsCanceled)
                {
                    Search(text);
                }
            }, TaskScheduler.FromCurrentSynchronizationContext());
    }
}

内存管理 #

及时释放资源 #

csharp
public partial class DetailPage : ContentPage
{
    private IDisposable _subscription;

    public DetailPage()
    {
        InitializeComponent();
        _subscription = Observable.Subscribe(OnNext);
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();
        _subscription?.Dispose();
    }
}

使用 WeakReference #

csharp
public class EventSubscriber
{
    private readonly WeakReference<Page> _pageRef;

    public EventSubscriber(Page page)
    {
        _pageRef = new WeakReference<Page>(page);
    }

    public void OnEvent(object sender, EventArgs e)
    {
        if (_pageRef.TryGetTarget(out var page))
        {
        }
    }
}

链接器配置 #

text
┌─────────────────────────────────────────────────────────────┐
│                    链接器选项                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Don't Link (不链接)                                        │
│  - 不移除任何代码                                           │
│  - 调试时使用                                               │
│  - 应用体积最大                                             │
│                                                             │
│  Link SDK Assemblies Only (仅链接 SDK)                      │
│  - 仅优化 SDK 程序集                                        │
│  - 平衡体积和兼容性                                         │
│  - 推荐用于发布                                             │
│                                                             │
│  Link All Assemblies (链接所有)                             │
│  - 优化所有程序集                                           │
│  - 应用体积最小                                             │
│  - 需要保留配置                                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘
xml
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
    <AndroidLinkMode>SdkOnly</AndroidLinkMode>
    <iOSLinkMode>SdkOnly</iOSLinkMode>
</PropertyGroup>
csharp
[assembly: Preserve(AllMembers = true)]
namespace MyApp.Services
{
    public class DataService
    {
    }
}

应用生命周期 #

应用生命周期事件 #

text
┌─────────────────────────────────────────────────────────────┐
│                    应用生命周期                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  启动流程:                                                  │
│                                                             │
│  App 构造函数                                                │
│       │                                                     │
│       ▼                                                     │
│  InitializeComponent()                                       │
│       │                                                     │
│       ▼                                                     │
│  OnStart()                                                   │
│       │                                                     │
│       ▼                                                     │
│  应用运行                                                    │
│       │                                                     │
│       ├── OnSleep() ──► 应用进入后台                        │
│       │        │                                            │
│       │        └── OnResume() ──► 应用恢复                  │
│       │                                                     │
│       ▼                                                     │
│  OnSleep()                                                   │
│       │                                                     │
│       ▼                                                     │
│  应用终止                                                    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

处理生命周期事件 #

csharp
public partial class App : Application
{
    public App()
    {
        InitializeComponent();
        MainPage = new AppShell();
    }

    protected override void OnStart()
    {
        Console.WriteLine("应用启动");
    }

    protected override void OnSleep()
    {
        Console.WriteLine("应用进入后台");
        SaveAppState();
    }

    protected override void OnResume()
    {
        Console.WriteLine("应用恢复");
        RestoreAppState();
    }

    private void SaveAppState()
    {
        var state = new AppState
        {
            LastPage = MainPage?.GetType().Name,
            Timestamp = DateTime.Now
        };
        Preferences.Set("app_state", JsonConvert.SerializeObject(state));
    }

    private void RestoreAppState()
    {
        var stateJson = Preferences.Get("app_state", string.Empty);
        if (!string.IsNullOrEmpty(stateJson))
        {
            var state = JsonConvert.DeserializeObject<AppState>(stateJson);
        }
    }
}

页面生命周期 #

csharp
public partial class DetailPage : ContentPage
{
    public DetailPage()
    {
        InitializeComponent();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        Console.WriteLine("页面即将显示");
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();
        Console.WriteLine("页面即将消失");
    }

    protected override void OnParentSet()
    {
        base.OnParentSet();
        Console.WriteLine("页面父级设置");
    }

    protected override void OnBindingContextChanged()
    {
        base.OnBindingContextChanged();
        Console.WriteLine("绑定上下文改变");
    }

    protected override bool OnBackButtonPressed()
    {
        Console.WriteLine("返回按钮按下");
        return base.OnBackButtonPressed();
    }
}

测试策略 #

单元测试 #

csharp
public class MainViewModelTests
{
    [Fact]
    public void LoadDataCommand_ShouldLoadItems()
    {
        var mockDataService = new Mock<IDataService>();
        mockDataService.Setup(s => s.GetItemsAsync())
            .ReturnsAsync(new List<Item> { new Item { Id = 1, Title = "Test" } });

        var viewModel = new MainViewModel(mockDataService.Object);

        viewModel.LoadDataCommand.Execute(null);

        Assert.Single(viewModel.Items);
        Assert.Equal("Test", viewModel.Items[0].Title);
    }

    [Fact]
    public void Title_WhenSet_ShouldRaisePropertyChanged()
    {
        var viewModel = new MainViewModel();
        var raised = false;
        
        viewModel.PropertyChanged += (s, e) =>
        {
            if (e.PropertyName == nameof(MainViewModel.Title))
            {
                raised = true;
            }
        };

        viewModel.Title = "New Title";

        Assert.True(raised);
    }
}

UI 测试 #

csharp
public class MainViewTests
{
    [Fact]
    public void MainPage_ShouldDisplayTitle()
    {
        var app = new App();
        var mainPage = app.MainPage as MainPage;

        var titleLabel = mainPage.FindByName<Label>("TitleLabel");

        Assert.NotNull(titleLabel);
        Assert.Equal("欢迎使用", titleLabel.Text);
    }
}

Xamarin.UITest #

csharp
public class Tests : BaseTest
{
    public Tests(Platform platform) : base(platform)
    {
    }

    [Test]
    public void AppLaunches()
    {
        app.Screenshot("First screen.");
    }

    [Test]
    public void LoginTest()
    {
        app.EnterText("UsernameEntry", "testuser");
        app.EnterText("PasswordEntry", "password123");
        app.Tap("LoginButton");
        
        app.WaitForElement("WelcomeLabel", "登录成功");
        app.Screenshot("登录成功");
    }
}

部署发布 #

Android 发布 #

text
┌─────────────────────────────────────────────────────────────┐
│                    Android 发布流程                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 配置应用信息                                            │
│     - AndroidManifest.xml                                   │
│     - 版本号、权限、图标                                    │
│                                                             │
│  2. 创建签名密钥                                            │
│     - keytool -genkey -v -keystore myapp.keystore          │
│                                                             │
│  3. 配置发布构建                                            │
│     - Release 模式                                          │
│     - 链接器设置                                            │
│     - AOT 编译                                              │
│                                                             │
│  4. 生成 APK/AAB                                            │
│     - 归档 (Archive)                                        │
│     - 签名                                                  │
│                                                             │
│  5. 上传到商店                                              │
│     - Google Play Console                                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

AndroidManifest.xml #

xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          android:versionCode="1"
          android:versionName="1.0"
          package="com.mycompany.myapp">
    
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
    
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    
    <application android:label="MyApp"
                 android:icon="@mipmap/ic_launcher"
                 android:roundIcon="@mipmap/ic_launcher_round">
    </application>
    
</manifest>

发布配置 #

xml
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugSymbols>false</DebugSymbols>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <AndroidLinkMode>SdkOnly</AndroidLinkMode>
    <AotAssemblies>true</AotAssemblies>
    <EnableLLVM>true</EnableLLVM>
    <AndroidEnableProfiledAot>true</AndroidEnableProfiledAot>
</PropertyGroup>

iOS 发布 #

text
┌─────────────────────────────────────────────────────────────┐
│                    iOS 发布流程                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 配置应用信息                                            │
│     - Info.plist                                            │
│     - 版本号、权限、图标                                    │
│                                                             │
│  2. 创建开发者证书                                          │
│     - Apple Developer 账户                                  │
│     - 创建 App ID                                          │
│     - 创建证书和描述文件                                    │
│                                                             │
│  3. 配置发布构建                                            │
│     - Release 模式                                          │
│     - AOT 编译                                              │
│     - LLVM 优化                                             │
│                                                             │
│  4. 生成 IPA                                                │
│     - 归档 (Archive)                                        │
│     - 签名                                                  │
│                                                             │
│  5. 上传到商店                                              │
│     - App Store Connect                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Info.plist #

xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleName</key>
    <string>MyApp</string>
    <key>CFBundleIdentifier</key>
    <string>com.mycompany.myapp</string>
    <key>CFBundleVersion</key>
    <string>1</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0</string>
    <key>MinimumOSVersion</key>
    <string>12.0</string>
    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>NSCameraUsageDescription</key>
    <string>需要访问相机来拍照</string>
</dict>
</plist>

迁移到 .NET MAUI #

MAUI 概述 #

text
┌─────────────────────────────────────────────────────────────┐
│                    .NET MAUI                                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  .NET MAUI 是 Xamarin.Forms 的继任者:                       │
│                                                             │
│  改进:                                                      │
│  ├── 统一项目结构                                          │
│  ├── 更好的性能                                            │
│  ├── 现代化 API                                            │
│  ├── .NET 6+ 支持                                          │
│  ├── 更好的热重载                                          │
│  └── 单一代码库                                            │
│                                                             │
│  平台支持:                                                  │
│  ├── Android                                               │
│  ├── iOS                                                   │
│  ├── macOS                                                 │
│  ├── Windows                                               │
│  └── Tizen                                                 │
│                                                             │
└─────────────────────────────────────────────────────────────┘

迁移步骤 #

text
┌─────────────────────────────────────────────────────────────┐
│                    迁移流程                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 评估迁移成本                                            │
│     - 检查 NuGet 依赖兼容性                                 │
│     - 检查自定义渲染器                                      │
│     - 检查 Effects                                          │
│                                                             │
│  2. 创建 MAUI 项目                                          │
│     - 使用迁移工具                                          │
│     - 或手动创建                                            │
│                                                             │
│  3. 迁移共享代码                                            │
│     - Models                                                │
│     - ViewModels                                            │
│     - Services                                              │
│                                                             │
│  4. 迁移 UI 代码                                            │
│     - XAML 文件                                             │
│     - 样式和资源                                            │
│                                                             │
│  5. 迁移平台代码                                            │
│     - 渲染器 → Handlers                                     │
│     - Effects                                               │
│     - 平台服务                                              │
│                                                             │
│  6. 测试和调试                                              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

API 变化 #

csharp
// Xamarin.Forms
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }
}

// .NET MAUI
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }
}
xml
<!-- Xamarin.Forms -->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

<!-- .NET MAUI -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

渲染器迁移到 Handlers #

csharp
// Xamarin.Forms 自定义渲染器
[assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))]
public class CustomButtonRenderer : ButtonRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
    {
        base.OnElementChanged(e);
        // 自定义逻辑
    }
}

// .NET MAUI Handler
public partial class CustomButtonHandler
{
    public static IPropertyMapper<CustomButton, CustomButtonHandler> Mapper =
        new PropertyMapper<CustomButton, CustomButtonHandler>(ButtonHandler.Mapper)
        {
            [nameof(CustomButton.CustomProperty)] = MapCustomProperty
        };

    public CustomButtonHandler() : base(Mapper)
    {
    }

    private static void MapCustomProperty(CustomButtonHandler handler, CustomButton button)
    {
        // 自定义逻辑
    }
}

最佳实践总结 #

代码组织 #

text
MyApp/
├── Models/                  # 数据模型
├── ViewModels/              # 视图模型
├── Views/                   # 视图
├── Services/                # 服务
├── Converters/              # 值转换器
├── Effects/                 # Effects
├── Renderers/               # 自定义渲染器
├── Helpers/                 # 辅助类
├── Resources/               # 资源
│   ├── Styles/
│   ├── Images/
│   └── Fonts/
└── Platforms/               # 平台特定代码
    ├── Android/
    ├── iOS/
    └── UWP/

性能检查清单 #

text
┌─────────────────────────────────────────────────────────────┐
│                    性能检查清单                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ✅ 启用 XAML 编译                                          │
│  ✅ 使用 Compiled Bindings                                  │
│  ✅ 使用 CollectionView 替代 ListView                       │
│  ✅ 配置正确的链接器选项                                    │
│  ✅ 使用异步操作避免 UI 阻塞                                │
│  ✅ 及时释放资源和取消订阅                                  │
│  ✅ 优化图片资源大小                                        │
│  ✅ 使用缓存减少网络请求                                    │
│  ✅ 避免过度布局嵌套                                        │
│  ✅ 延迟加载非必要组件                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

总结 #

恭喜你完成了 Xamarin.Forms 完全指南的学习!你已经掌握了:

  • Xamarin 的基础概念和开发环境配置
  • XAML 语法和页面布局
  • 导航系统和数据绑定
  • MVVM 架构模式
  • 样式和资源管理
  • 平台特性调用
  • 性能优化和部署发布

继续实践,探索更多高级功能,并考虑迁移到 .NET MAUI 以获得更好的开发体验!

最后更新:2026-03-29