<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>Resmic's | BLOG</title><link>https://blog.resmic.cn/</link><description>个人博客</description><item><title>PHP 8.1 Fibers协程实战：构建高性能异步任务调度器</title><link>https://blog.resmic.cn/post/307.html</link><description>&lt;p&gt;&lt;img src=&quot;https://blog.resmic.cn/zb_users/upload/2026/06/20260627080446178251868660407.jpg&quot; alt=&quot;封面&quot; style=&quot;width:100%;&quot;&gt;&lt;/p&gt;

&lt;h2&gt;什么是 PHP Fibers（协程）？&lt;/h2&gt;
&lt;p&gt;PHP 8.1 正式引入了 &lt;strong&gt;Fibers&lt;/strong&gt;（纤程/协程），这是 PHP 并发编程领域一次重大突破。Fibers 提供了一种轻量级的协作式多任务机制，允许开发者暂停和恢复代码执行，而无需借助操作系统线程或多进程。&lt;/p&gt;
&lt;p&gt;与传统的 &lt;code&gt;Generator&lt;/code&gt; 类似，Fibers 可以在执行过程中被挂起，但它更强大：Fibers 可以从调用栈的任意深度暂停，而不仅仅是直接在 &lt;code&gt;yield&lt;/code&gt; 语句处。这使得构建异步框架、事件循环和协程调度器成为可能。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
// 创建一个基本的 Fiber
$fiber = new Fiber(function(): void {
    $value = Fiber::suspend('first suspend');
    echo &quot;Fiber received: &quot; . $value . PHP_EOL;
    Fiber::suspend('second suspend');
    echo &quot;Fiber resumed again&quot; . PHP_EOL;
});

$result1 = $fiber-&gt;start();         // 输出: first suspend
echo &quot;Main got: $result1&quot; . PHP_EOL;

$result2 = $fiber-&gt;resume('hello'); // 输出: Fiber received: hello
echo &quot;Main got: $result2&quot; . PHP_EOL;

$fiber-&gt;resume(); // 输出: Fiber resumed again
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Fibers 核心 API 详解&lt;/h2&gt;
&lt;p&gt;PHP Fibers 的 API 设计十分简洁，主要包含以下方法：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;new Fiber(callable $callback)&lt;/code&gt;：创建一个新的 Fiber 实例，传入要执行的回调函数&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fiber::start(...$args)&lt;/code&gt;：启动 Fiber，传入初始参数，返回 &lt;code&gt;Fiber::suspend()&lt;/code&gt; 的值&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fiber::resume(mixed $value)&lt;/code&gt;：从上次 suspend 处恢复执行，传入值给 suspend 调用方&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fiber::suspend(mixed $value)&lt;/code&gt;：暂停当前 Fiber，将值传递给 resume/start 的调用方&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fiber::isStarted()&lt;/code&gt;：检查 Fiber 是否已启动&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fiber::isRunning()&lt;/code&gt;：检查 Fiber 当前是否正在运行&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fiber::isSuspended()&lt;/code&gt;：检查 Fiber 是否处于挂起状态&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fiber::isTerminated()&lt;/code&gt;：检查 Fiber 是否已终止&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;Fiber::getReturn()&lt;/code&gt;：获取 Fiber 的返回值（必须在 terminated 后调用）&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
$fiber = new Fiber(function(): string {
    echo &quot;Step 1&quot; . PHP_EOL;
    Fiber::suspend();
    echo &quot;Step 2&quot; . PHP_EOL;
    Fiber::suspend();
    echo &quot;Step 3&quot; . PHP_EOL;
    return &quot;done&quot;;
});

$fiber-&gt;start();
var_dump($fiber-&gt;isStarted());    // bool(true)
var_dump($fiber-&gt;isSuspended());  // bool(true)
var_dump($fiber-&gt;isTerminated()); // bool(false)

$fiber-&gt;resume();
$fiber-&gt;resume();
var_dump($fiber-&gt;isTerminated()); // bool(true)
echo $fiber-&gt;getReturn() . PHP_EOL; // done
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;构建轻量级事件循环调度器&lt;/h2&gt;
&lt;p&gt;Fibers 最重要的应用场景是构建事件循环。下面演示一个简单但功能完整的任务调度器，可以并发执行多个异步任务：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
class EventLoop
{
    /** @var Fiber[] */
    private array $fibers = [];

    public function add(callable $callback): void
    {
        $this-&gt;fibers[] = new Fiber($callback);
    }

    public function run(): void
    {
        // 启动所有 Fiber
        foreach ($this-&gt;fibers as $fiber) {
            $fiber-&gt;start();
        }

        // 循环直到所有 Fiber 终止
        while (true) {
            $allDone = true;
            foreach ($this-&gt;fibers as $fiber) {
                if (!$fiber-&gt;isTerminated()) {
                    $allDone = false;
                    if ($fiber-&gt;isSuspended()) {
                        $fiber-&gt;resume();
                    }
                }
            }
            if ($allDone) break;
        }
    }
}

// 使用示例
$loop = new EventLoop();

$loop-&gt;add(function(): void {
    echo &quot;[Task 1] 开始处理请求...&quot; . PHP_EOL;
    Fiber::suspend(); // 模拟 IO 等待
    echo &quot;[Task 1] IO 完成，处理数据...&quot; . PHP_EOL;
    Fiber::suspend();
    echo &quot;[Task 1] 完成&quot; . PHP_EOL;
});

$loop-&gt;add(function(): void {
    echo &quot;[Task 2] 开始查询数据库...&quot; . PHP_EOL;
    Fiber::suspend();
    echo &quot;[Task 2] 查询完毕，格式化结果...&quot; . PHP_EOL;
    Fiber::suspend();
    echo &quot;[Task 2] 完成&quot; . PHP_EOL;
});

$loop-&gt;run();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出结果展示了两个任务交替执行，而非顺序阻塞执行——这正是协程的核心价值。&lt;/p&gt;

&lt;h2&gt;与 ReactPHP / Swoole 的配合使用&lt;/h2&gt;
&lt;p&gt;Fibers 本身只是底层机制，在实际项目中通常配合成熟的异步框架使用。&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;ReactPHP&lt;/strong&gt;：从 v1.2.0 起全面支持 Fibers，可以用同步写法调用异步 API&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Swoole&lt;/strong&gt;：内置 Coroutine 与 PHP Fibers 深度集成，性能更强&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Amp&lt;/strong&gt;：v3.0 以 Fibers 为核心重新设计，提供更友好的异步 API&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Revolt&lt;/strong&gt;：专为 PHP Fibers 设计的事件循环底层库，被多个框架采用&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
// 使用 Amp v3 的 Fibers 风格
use Amp\Future;
use function Amp\async;
use function Amp\await;

// 并发发起多个 HTTP 请求
$futures = [
    async(fn() =&gt; fetchUrl('https://api.example.com/users')),
    async(fn() =&gt; fetchUrl('https://api.example.com/orders')),
    async(fn() =&gt; fetchUrl('https://api.example.com/products')),
];

// 等待所有请求完成（并发执行）
[$users, $orders, $products] = Future\await($futures);
echo &quot;获取到 &quot; . count($users) . &quot; 个用户&quot; . PHP_EOL;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;实践建议与性能对比&lt;/h2&gt;
&lt;p&gt;在实际项目中使用 Fibers 时，有几点需要特别注意：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;适合 IO 密集型场景&lt;/strong&gt;：数据库查询、HTTP 调用、文件读写——这些 IO 等待时间可被其他 Fiber 利用&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;不适合 CPU 密集型&lt;/strong&gt;：Fibers 是协作式（非抢占式），CPU 密集计算会阻塞整个事件循环&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;错误处理&lt;/strong&gt;：Fiber 内抛出的异常会在 &lt;code&gt;resume()&lt;/code&gt; 或 &lt;code&gt;start()&lt;/code&gt; 处传播到调用方&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;内存开销&lt;/strong&gt;：每个 Fiber 需要约 8KB 栈空间，远低于线程（通常 1-8MB）&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;PHP 版本要求&lt;/strong&gt;：Fibers 需要 PHP 8.1+，8.3 版本进一步优化了性能&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;根据基准测试，在高并发 HTTP 服务场景中，使用 Fibers + ReactPHP 的 PHP 应用吞吐量可达传统同步模式的 &lt;strong&gt;5-10 倍&lt;/strong&gt;，内存占用仅增加 20%-30%，是提升 PHP 应用性能的高性价比方案。&lt;/p&gt;
&lt;p&gt;如果你的项目运行在 PHP 8.1+ 环境，现在就是拥抱 Fibers 异步编程的最佳时机！&lt;/p&gt;
</description><pubDate>Sat, 27 Jun 2026 08:10:26 +0800</pubDate></item><item><title>PHP 8.4 新特性全解析：属性钩子、非对称可见性与性能提升</title><link>https://blog.resmic.cn/post/306.html</link><description>&lt;p&gt;PHP 8.4 带来了属性钩子（Property Hooks）、非对称可见性（Asymmetric Visibility）等重磅特性，同时对数组、字符串函数库进行了扩充，JIT 性能进一步提升。本文带你快速上手这些新特性，了解其使用场景和注意事项，助你写出更优雅的现代 PHP 代码。&lt;/p&gt;</description><pubDate>Fri, 26 Jun 2026 08:11:40 +0800</pubDate></item><item><title>Jetpack Compose 性能优化实战：告别卡顿的8大核心技巧</title><link>https://blog.resmic.cn/post/305.html</link><description>&lt;p&gt;&lt;img src=&quot;https://blog.resmic.cn/zb_users/upload/2026/06/20260625081028178234622819184.jpg&quot; alt=&quot;封面&quot; style=&quot;width:100%;&quot;/&gt;&lt;/p&gt;&lt;h2&gt;为什么 Compose 性能优化如此重要&lt;/h2&gt;&lt;p&gt;Jetpack Compose 采用声明式 UI 范式，通过重组（Recomposition）机制更新界面。然而，不合理的代码结构会导致不必要的重组，造成界面卡顿、掉帧，严重影响用户体验。&lt;/p&gt;&lt;p&gt;与传统 View 系统相比，Compose 的重组机制更为智能，但开发者仍需理解其工作原理，才能写出高性能的 Composable 函数。&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;过度重组是 Compose 性能问题的主要根源&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;状态读取位置直接影响重组范围&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;不稳定的类型会强制触发全量重组&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;合理使用 remember 和派生状态可显著减少重组次数&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;理解重组机制与 Skipping 优化&lt;/h2&gt;&lt;p&gt;Compose 编译器会为每个 Composable 函数生成重组代码。当状态变化时，只有读取了该状态的 Composable 才会触发重组。理解这一机制是优化的前提。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Skippable Composable&lt;/strong&gt; 是指当参数未发生变化时，Compose 可以跳过该函数的重组。要使 Composable 可跳过，其所有参数必须是稳定类型。&lt;/p&gt;&lt;pre&gt;//&amp;nbsp;❌&amp;nbsp;不可跳过&amp;nbsp;-&amp;nbsp;List&amp;nbsp;是不稳定类型
@Composable
fun&amp;nbsp;UserList(users:&amp;nbsp;List&amp;lt;User&amp;gt;)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;每次父组件重组都会重组
}

//&amp;nbsp;✅&amp;nbsp;可跳过&amp;nbsp;-&amp;nbsp;使用&amp;nbsp;@Immutable&amp;nbsp;标注的稳定类型
@Immutable
data&amp;nbsp;class&amp;nbsp;UserListState(val&amp;nbsp;users:&amp;nbsp;List&amp;lt;User&amp;gt;)

@Composable
fun&amp;nbsp;UserList(state:&amp;nbsp;UserListState)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;仅在&amp;nbsp;state&amp;nbsp;变化时重组
}&lt;/pre&gt;&lt;p&gt;使用 Compose Compiler Report 可以查看哪些 Composable 是可跳过的，哪些参数是不稳定的：&lt;/p&gt;&lt;pre&gt;//&amp;nbsp;build.gradle.kts
tasks.withType&amp;lt;KotlinCompile&amp;gt;().configureEach&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;compilerOptions&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;freeCompilerArgs.addAll(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;-P&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${project.buildDir.absolutePath}/compose_reports&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;h2&gt;状态管理与读取位置优化&lt;/h2&gt;&lt;p&gt;状态读取的位置决定了重组的范围。将状态读取下推到尽可能小的 Composable 中，可以最小化重组范围。&lt;/p&gt;&lt;pre&gt;//&amp;nbsp;❌&amp;nbsp;在父组件读取状态，导致整个父组件重组
@Composable
fun&amp;nbsp;ParentComposable(viewModel:&amp;nbsp;MyViewModel)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;uiState&amp;nbsp;by&amp;nbsp;viewModel.uiState.collectAsState()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Column&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HeaderSection()&amp;nbsp;&amp;nbsp;//&amp;nbsp;不需要&amp;nbsp;uiState&amp;nbsp;但也会重组
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ContentSection(text&amp;nbsp;=&amp;nbsp;uiState.text)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FooterSection()&amp;nbsp;&amp;nbsp;//&amp;nbsp;不需要&amp;nbsp;uiState&amp;nbsp;但也会重组
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

//&amp;nbsp;✅&amp;nbsp;将状态传递到叶子节点，或使用&amp;nbsp;lambda&amp;nbsp;延迟读取
@Composable
fun&amp;nbsp;ParentComposable(viewModel:&amp;nbsp;MyViewModel)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Column&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HeaderSection()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ContentSection(textProvider&amp;nbsp;=&amp;nbsp;{&amp;nbsp;viewModel.uiState.value.text&amp;nbsp;})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FooterSection()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;derivedStateOf&lt;/strong&gt; 是减少重组的利器，当计算结果不变时不会触发下游重组：&lt;/p&gt;&lt;pre&gt;@Composable
fun&amp;nbsp;ScrollableList()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;listState&amp;nbsp;=&amp;nbsp;rememberLazyListState()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;✅&amp;nbsp;只有&amp;nbsp;showButton&amp;nbsp;实际改变时才触发重组
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;showButton&amp;nbsp;by&amp;nbsp;remember&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;derivedStateOf&amp;nbsp;{&amp;nbsp;listState.firstVisibleItemIndex&amp;nbsp;&amp;gt;&amp;nbsp;0&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Box&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LazyColumn(state&amp;nbsp;=&amp;nbsp;listState)&amp;nbsp;{&amp;nbsp;/*&amp;nbsp;items&amp;nbsp;*/&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(showButton)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ScrollToTopButton()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;h2&gt;LazyList 性能优化实战&lt;/h2&gt;&lt;p&gt;LazyColumn 和 LazyRow 是 Compose 中最常用的列表组件，也是性能问题的高发区。以下是几个关键优化点：&lt;/p&gt;&lt;h3&gt;为 Item 指定稳定的 key&lt;/h3&gt;&lt;pre&gt;//&amp;nbsp;❌&amp;nbsp;没有&amp;nbsp;key，滚动后状态丢失，全量重组
LazyColumn&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items(users)&amp;nbsp;{&amp;nbsp;user&amp;nbsp;-&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UserItem(user&amp;nbsp;=&amp;nbsp;user)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

//&amp;nbsp;✅&amp;nbsp;指定稳定&amp;nbsp;key，只更新变化的&amp;nbsp;item
LazyColumn&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items&amp;nbsp;=&amp;nbsp;users,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;key&amp;nbsp;=&amp;nbsp;{&amp;nbsp;user&amp;nbsp;-&amp;gt;&amp;nbsp;user.id&amp;nbsp;}&amp;nbsp;&amp;nbsp;//&amp;nbsp;使用唯一稳定标识
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&amp;nbsp;{&amp;nbsp;user&amp;nbsp;-&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UserItem(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;user&amp;nbsp;=&amp;nbsp;user,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modifier&amp;nbsp;=&amp;nbsp;Modifier.animateItem()&amp;nbsp;&amp;nbsp;//&amp;nbsp;支持动画
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;h3&gt;使用 contentType 优化 Item 复用&lt;/h3&gt;&lt;pre&gt;LazyColumn&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items&amp;nbsp;=&amp;nbsp;feedItems,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;key&amp;nbsp;=&amp;nbsp;{&amp;nbsp;it.id&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;contentType&amp;nbsp;=&amp;nbsp;{&amp;nbsp;item&amp;nbsp;-&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when&amp;nbsp;(item)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;is&amp;nbsp;FeedItem.Post&amp;nbsp;-&amp;gt;&amp;nbsp;&amp;quot;post&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;is&amp;nbsp;FeedItem.Ad&amp;nbsp;-&amp;gt;&amp;nbsp;&amp;quot;ad&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;is&amp;nbsp;FeedItem.Story&amp;nbsp;-&amp;gt;&amp;nbsp;&amp;quot;story&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&amp;nbsp;{&amp;nbsp;item&amp;nbsp;-&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when&amp;nbsp;(item)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;is&amp;nbsp;FeedItem.Post&amp;nbsp;-&amp;gt;&amp;nbsp;PostItem(item)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;is&amp;nbsp;FeedItem.Ad&amp;nbsp;-&amp;gt;&amp;nbsp;AdItem(item)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;is&amp;nbsp;FeedItem.Story&amp;nbsp;-&amp;gt;&amp;nbsp;StoryItem(item)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;h3&gt;避免在 Item 中创建 Lambda&lt;/h3&gt;&lt;pre&gt;//&amp;nbsp;❌&amp;nbsp;每次重组创建新&amp;nbsp;lambda，导致&amp;nbsp;item&amp;nbsp;不可跳过
@Composable
fun&amp;nbsp;FeedScreen(viewModel:&amp;nbsp;FeedViewModel)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;items&amp;nbsp;by&amp;nbsp;viewModel.items.collectAsState()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LazyColumn&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items(items,&amp;nbsp;key&amp;nbsp;=&amp;nbsp;{&amp;nbsp;it.id&amp;nbsp;})&amp;nbsp;{&amp;nbsp;item&amp;nbsp;-&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PostItem(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item&amp;nbsp;=&amp;nbsp;item,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;onLike&amp;nbsp;=&amp;nbsp;{&amp;nbsp;viewModel.likePost(item.id)&amp;nbsp;}&amp;nbsp;&amp;nbsp;//&amp;nbsp;每次重组新建
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

//&amp;nbsp;✅&amp;nbsp;将回调提升，稳定引用
@Composable
fun&amp;nbsp;FeedScreen(viewModel:&amp;nbsp;FeedViewModel)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;items&amp;nbsp;by&amp;nbsp;viewModel.items.collectAsState()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;onLike&amp;nbsp;=&amp;nbsp;remember&amp;nbsp;{&amp;nbsp;{&amp;nbsp;id:&amp;nbsp;String&amp;nbsp;-&amp;gt;&amp;nbsp;viewModel.likePost(id)&amp;nbsp;}&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LazyColumn&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items(items,&amp;nbsp;key&amp;nbsp;=&amp;nbsp;{&amp;nbsp;it.id&amp;nbsp;})&amp;nbsp;{&amp;nbsp;item&amp;nbsp;-&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PostItem(item&amp;nbsp;=&amp;nbsp;item,&amp;nbsp;onLike&amp;nbsp;=&amp;nbsp;onLike)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;h2&gt;稳定性注解的正确使用&lt;/h2&gt;&lt;p&gt;Compose 编译器通过分析类型的稳定性来决定是否可以跳过重组。理解并正确使用稳定性注解，是高级 Compose 优化的关键。&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;@Stable&lt;/strong&gt;：标注类是稳定的，但允许属性可变（需保证变化时通知 Compose）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;@Immutable&lt;/strong&gt;：标注类是完全不可变的，是最强的稳定性保证&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;//&amp;nbsp;对于&amp;nbsp;ViewModel&amp;nbsp;暴露的&amp;nbsp;UI&amp;nbsp;State，使用&amp;nbsp;@Immutable
@Immutable
data&amp;nbsp;class&amp;nbsp;HomeUiState(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;isLoading:&amp;nbsp;Boolean&amp;nbsp;=&amp;nbsp;false,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;posts:&amp;nbsp;ImmutableList&amp;lt;Post&amp;gt;&amp;nbsp;=&amp;nbsp;persistentListOf(),&amp;nbsp;&amp;nbsp;//&amp;nbsp;使用&amp;nbsp;kotlinx.collections.immutable
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;error:&amp;nbsp;String?&amp;nbsp;=&amp;nbsp;null
)

//&amp;nbsp;ViewModel
class&amp;nbsp;HomeViewModel&amp;nbsp;:&amp;nbsp;ViewModel()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;val&amp;nbsp;_uiState&amp;nbsp;=&amp;nbsp;MutableStateFlow(HomeUiState())
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;uiState:&amp;nbsp;StateFlow&amp;lt;HomeUiState&amp;gt;&amp;nbsp;=&amp;nbsp;_uiState.asStateFlow()
}

//&amp;nbsp;使用&amp;nbsp;kotlinx.collections.immutable&amp;nbsp;解决集合不稳定问题
//&amp;nbsp;build.gradle.kts
implementation(&amp;quot;org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7&amp;quot;)&lt;/pre&gt;&lt;p&gt;对于第三方库中无法修改的类型，可以通过创建包装类来解决稳定性问题：&lt;/p&gt;&lt;pre&gt;@Immutable
@JvmInline
value&amp;nbsp;class&amp;nbsp;StableWrapper&amp;lt;T&amp;gt;(val&amp;nbsp;value:&amp;nbsp;T)

//&amp;nbsp;使用
@Composable
fun&amp;nbsp;MapScreen(location:&amp;nbsp;StableWrapper&amp;lt;LatLng&amp;gt;)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;location&amp;nbsp;现在是稳定的
}&lt;/pre&gt;&lt;h2&gt;图片加载与内存优化&lt;/h2&gt;&lt;p&gt;图片加载是 Android 应用性能的重要环节，Coil 是目前 Compose 生态中最推荐的图片加载库。&lt;/p&gt;&lt;pre&gt;//&amp;nbsp;build.gradle.kts
implementation(&amp;quot;io.coil-kt:coil-compose:2.6.0&amp;quot;)

//&amp;nbsp;基础使用
@Composable
fun&amp;nbsp;UserAvatar(imageUrl:&amp;nbsp;String)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AsyncImage(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;model&amp;nbsp;=&amp;nbsp;ImageRequest.Builder(LocalContext.current)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.data(imageUrl)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.crossfade(true)&amp;nbsp;&amp;nbsp;//&amp;nbsp;淡入动画
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.memoryCachePolicy(CachePolicy.ENABLED)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.diskCachePolicy(CachePolicy.ENABLED)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.build(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;contentDescription&amp;nbsp;=&amp;nbsp;&amp;quot;用户头像&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modifier&amp;nbsp;=&amp;nbsp;Modifier
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.size(48.dp)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.clip(CircleShape),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;contentScale&amp;nbsp;=&amp;nbsp;ContentScale.Crop,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;placeholder&amp;nbsp;=&amp;nbsp;painterResource(R.drawable.avatar_placeholder),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;error&amp;nbsp;=&amp;nbsp;painterResource(R.drawable.avatar_error)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
}&lt;/pre&gt;&lt;p&gt;对于列表中的图片，合理设置尺寸可以避免加载过大的图片：&lt;/p&gt;&lt;pre&gt;AsyncImage(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;model&amp;nbsp;=&amp;nbsp;ImageRequest.Builder(LocalContext.current)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.data(imageUrl)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.size(Size(200,&amp;nbsp;200))&amp;nbsp;&amp;nbsp;//&amp;nbsp;指定加载尺寸
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.scale(Scale.FILL)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.build(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;contentDescription&amp;nbsp;=&amp;nbsp;null
)&lt;/pre&gt;&lt;h2&gt;使用 Baseline Profile 提升冷启动性能&lt;/h2&gt;&lt;p&gt;Baseline Profile 是 Android 性能优化的重要手段，可以预编译关键代码路径，显著提升应用冷启动速度和运行时性能。对于 Compose 应用尤其重要，因为 Compose 框架本身的代码量较大。&lt;/p&gt;&lt;pre&gt;//&amp;nbsp;build.gradle.kts（app&amp;nbsp;模块）
plugins&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;id(&amp;quot;androidx.baselineprofile&amp;quot;)
}

dependencies&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;baselineProfile(project(&amp;quot;:baseline-profile&amp;quot;))
}

//&amp;nbsp;baseline-profile&amp;nbsp;模块
@RunWith(AndroidJUnit4::class)
class&amp;nbsp;BaselineProfileGenerator&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@get:Rule
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;rule&amp;nbsp;=&amp;nbsp;BaselineProfileRule()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Test
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fun&amp;nbsp;generate()&amp;nbsp;=&amp;nbsp;rule.collect(&amp;quot;com.example.app&amp;quot;)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;模拟用户关键路径
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pressHome()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;startActivityAndWait()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;滚动主列表
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;device.findObject(By.res(&amp;quot;feed_list&amp;quot;)).also&amp;nbsp;{&amp;nbsp;list&amp;nbsp;-&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;list.fling(Direction.DOWN)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;list.fling(Direction.UP)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;p&gt;生成 Baseline Profile 后，将其提交到版本控制。在 Release 构建时，AGP 会自动将 Profile 编译进 APK，用户首次启动时无需 JIT 编译，直接运行 AOT 优化后的代码，启动速度可提升 30%~40%。&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;冷启动时间减少 20%-40%&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;列表滚动 jank 减少&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;用户操作响应更流畅&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;配合 Macrobenchmark 持续监控性能回归&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;性能监控与调试工具&lt;/h2&gt;&lt;p&gt;优化必须基于数据。以下是 Compose 性能调试的必备工具：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Layout Inspector&lt;/strong&gt;：实时查看 Compose 层级和重组次数（Android Studio 内置）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Macrobenchmark&lt;/strong&gt;：在真实设备上测量启动时间、帧率等指标&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Perfetto&lt;/strong&gt;：系统级性能追踪，查看帧渲染时间线&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compose Compiler Report&lt;/strong&gt;：分析 Composable 的稳定性和可跳过性&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;//&amp;nbsp;在&amp;nbsp;Debug&amp;nbsp;构建中启用重组计数
@Composable
fun&amp;nbsp;RecompositionCounter(content:&amp;nbsp;@Composable&amp;nbsp;()&amp;nbsp;-&amp;gt;&amp;nbsp;Unit)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;count&amp;nbsp;=&amp;nbsp;remember&amp;nbsp;{&amp;nbsp;mutableIntStateOf(0)&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SideEffect&amp;nbsp;{&amp;nbsp;count.intValue++&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Box&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;content()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(BuildConfig.DEBUG)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Text(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;text&amp;nbsp;=&amp;nbsp;&amp;quot;重组:${count.intValue}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modifier&amp;nbsp;=&amp;nbsp;Modifier
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.align(Alignment.TopEnd)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.background(Color.Red.copy(alpha&amp;nbsp;=&amp;nbsp;0.7f))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.padding(2.dp),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color&amp;nbsp;=&amp;nbsp;Color.White,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fontSize&amp;nbsp;=&amp;nbsp;10.sp
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;p&gt;通过以上系统性的优化手段，结合持续的性能监控，你的 Compose 应用将能够在各种设备上保持流畅的 60fps 体验。性能优化是一个持续的过程，建议在项目早期就建立性能基准和监控体系，防止性能回归。&lt;/p&gt;</description><pubDate>Thu, 25 Jun 2026 08:10:46 +0800</pubDate></item><item><title>深度解析 AI Agent 工作流：从理论到生产实践的完整指南</title><link>https://blog.resmic.cn/post/304.html</link><description>&lt;p&gt;&lt;img src=&quot;https://blog.resmic.cn/zb_users/upload/2026/06/20260624080725178225964535583.jpg&quot; alt=&quot;封面&quot; style=&quot;width:100%;&quot;/&gt;&lt;/p&gt;&lt;h2&gt;一、AI Agent 的本质：不只是&amp;quot;会用工具的 LLM&amp;quot;&lt;/h2&gt;&lt;p&gt;近两年，&amp;quot;AI Agent&amp;quot;这个词几乎出现在所有大模型相关的讨论中。但在实际落地时，很多团队发现：Demo 跑起来很酷，一到生产就翻车。原因往往不在模型本身，而在于对 Agent 架构的理解不够深入。&lt;/p&gt;&lt;p&gt;从本质上看，AI Agent 是一个&lt;strong&gt;具备自主决策能力的循环系统&lt;/strong&gt;。它不只是接收一个问题然后返回答案，而是能够：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;感知环境&lt;/strong&gt;：接收用户输入、工具返回、上下文状态&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;规划行动&lt;/strong&gt;：根据目标分解任务、选择工具&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;执行操作&lt;/strong&gt;：调用外部 API、执行代码、检索信息&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;反思结果&lt;/strong&gt;：评估执行结果，决定下一步&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;记忆管理&lt;/strong&gt;：维护短期和长期记忆，跨轮次保持上下文&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这个循环可以持续运转，直到任务完成或遇到需要人工介入的情况。理解这个本质，是构建可靠 Agent 系统的第一步。&lt;/p&gt;&lt;h2&gt;二、ReAct 模式：Agent 工作流的基石&lt;/h2&gt;&lt;p&gt;目前最主流的 Agent 推理框架是 &lt;strong&gt;ReAct（Reason + Act）&lt;/strong&gt;，由 Yao et al. 在 2022 年提出。其核心思想是让 LLM 交替进行&amp;quot;思考&amp;quot;和&amp;quot;行动&amp;quot;，形成 Thought → Action → Observation 的循环。&lt;/p&gt;&lt;pre&gt;Thought:&amp;nbsp;用户想查询北京今天的天气，我需要调用天气&amp;nbsp;API
Action:&amp;nbsp;call_weather_api(city=&amp;quot;北京&amp;quot;,&amp;nbsp;date=&amp;quot;2026-06-24&amp;quot;)
Observation:&amp;nbsp;{&amp;quot;temp&amp;quot;:&amp;nbsp;32,&amp;nbsp;&amp;quot;weather&amp;quot;:&amp;nbsp;&amp;quot;晴&amp;quot;,&amp;nbsp;&amp;quot;humidity&amp;quot;:&amp;nbsp;45}
Thought:&amp;nbsp;已获取天气数据，现在可以给用户回复了
Action:&amp;nbsp;final_answer(&amp;quot;北京今天天气晴，气温32°C，湿度45%&amp;quot;)&lt;/pre&gt;&lt;p&gt;这种模式有几个关键优点：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;可解释性强&lt;/strong&gt;：每一步推理都有迹可循，便于调试&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;错误可恢复&lt;/strong&gt;：Observation 失败时，模型可以重新规划&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;工具解耦&lt;/strong&gt;：工具定义与推理逻辑分离，易于扩展&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;在实际工程实现中，ReAct 通常通过&lt;strong&gt;函数调用（Function Calling）&lt;/strong&gt;来落地。以 OpenAI 兼容接口为例：&lt;/p&gt;&lt;pre&gt;tools&amp;nbsp;=&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;type&amp;quot;:&amp;nbsp;&amp;quot;function&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;function&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;name&amp;quot;:&amp;nbsp;&amp;quot;get_weather&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;description&amp;quot;:&amp;nbsp;&amp;quot;获取指定城市的天气信息&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;parameters&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;type&amp;quot;:&amp;nbsp;&amp;quot;object&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;properties&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;city&amp;quot;:&amp;nbsp;{&amp;quot;type&amp;quot;:&amp;nbsp;&amp;quot;string&amp;quot;,&amp;nbsp;&amp;quot;description&amp;quot;:&amp;nbsp;&amp;quot;城市名称&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;date&amp;quot;:&amp;nbsp;{&amp;quot;type&amp;quot;:&amp;nbsp;&amp;quot;string&amp;quot;,&amp;nbsp;&amp;quot;description&amp;quot;:&amp;nbsp;&amp;quot;日期，格式&amp;nbsp;YYYY-MM-DD&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;required&amp;quot;:&amp;nbsp;[&amp;quot;city&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
]

response&amp;nbsp;=&amp;nbsp;client.chat.completions.create(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;model=&amp;quot;gpt-4o&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;messages=messages,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tools=tools,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tool_choice=&amp;quot;auto&amp;quot;
)&lt;/pre&gt;&lt;p&gt;当模型决定调用工具时，会返回 &lt;code&gt;tool_calls&lt;/code&gt; 字段，你的代码负责执行，将结果以 &lt;code&gt;role: &amp;quot;tool&amp;quot;&lt;/code&gt; 的消息追加回去，再次请求模型，如此循环。&lt;/p&gt;&lt;h2&gt;三、工具设计原则：好工具是 Agent 成功的关键&lt;/h2&gt;&lt;p&gt;工具质量直接决定 Agent 的能力上限。很多开发者在工具设计上犯的错误，比模型选择的影响还要大。以下是经过生产验证的工具设计原则：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. 单一职责&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;每个工具只做一件事。避免&amp;quot;万能工具&amp;quot;——一个工具参数越多，模型调用出错的概率就越高。&lt;/p&gt;&lt;pre&gt;#&amp;nbsp;❌&amp;nbsp;糟糕的设计：一个工具做太多事
def&amp;nbsp;database_operation(action:&amp;nbsp;str,&amp;nbsp;table:&amp;nbsp;str,&amp;nbsp;data:&amp;nbsp;dict&amp;nbsp;=&amp;nbsp;None,&amp;nbsp;query:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;None):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;action&amp;nbsp;==&amp;nbsp;&amp;quot;read&amp;quot;:&amp;nbsp;...
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elif&amp;nbsp;action&amp;nbsp;==&amp;nbsp;&amp;quot;write&amp;quot;:&amp;nbsp;...
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elif&amp;nbsp;action&amp;nbsp;==&amp;nbsp;&amp;quot;delete&amp;quot;:&amp;nbsp;...

#&amp;nbsp;✅&amp;nbsp;好的设计：分开定义
def&amp;nbsp;query_records(table:&amp;nbsp;str,&amp;nbsp;filters:&amp;nbsp;dict)&amp;nbsp;-&amp;gt;&amp;nbsp;list:&amp;nbsp;...
def&amp;nbsp;insert_record(table:&amp;nbsp;str,&amp;nbsp;data:&amp;nbsp;dict)&amp;nbsp;-&amp;gt;&amp;nbsp;str:&amp;nbsp;...
def&amp;nbsp;delete_record(table:&amp;nbsp;str,&amp;nbsp;record_id:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:&amp;nbsp;...&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;2. 描述要精准&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;工具的 &lt;code&gt;description&lt;/code&gt; 不是写给人看的注释，而是模型的&amp;quot;说明书&amp;quot;。要明确说明：什么情况下用、参数含义、返回值格式、副作用（是否有写操作）。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3. 幂等性设计&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;网络超时、模型重试都可能导致工具被调用多次。查询类工具天然幂等，写操作需要通过唯一 ID 或条件检查来保证幂等。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;4. 结构化返回值&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;工具返回 JSON 而非自然语言字符串。模型处理结构化数据更准确，也便于后续的错误检测。&lt;/p&gt;&lt;h2&gt;四、记忆管理：让 Agent 拥有&amp;quot;真正的记忆&amp;quot;&lt;/h2&gt;&lt;p&gt;Agent 的记忆系统通常分为四个层次：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;感知缓冲（Context Window）&lt;/strong&gt;：当前对话的完整上下文，受 Token 限制&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;短期记忆（Working Memory）&lt;/strong&gt;：本次任务的中间状态，如变量值、已完成的子任务&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;长期记忆（Long-term Memory）&lt;/strong&gt;：跨会话的用户偏好、历史摘要，通常存向量数据库&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;外部知识（External Knowledge）&lt;/strong&gt;：RAG 检索的文档、实时数据&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Context Window 管理是最常见的工程挑战。当对话历史超出限制时，常用策略：&lt;/p&gt;&lt;pre&gt;class&amp;nbsp;ContextManager:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;max_tokens:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;16000):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.max_tokens&amp;nbsp;=&amp;nbsp;max_tokens
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.messages&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;add_message(self,&amp;nbsp;role:&amp;nbsp;str,&amp;nbsp;content:&amp;nbsp;str):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.messages.append({&amp;quot;role&amp;quot;:&amp;nbsp;role,&amp;nbsp;&amp;quot;content&amp;quot;:&amp;nbsp;content})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._trim_if_needed()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_trim_if_needed(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;保留系统消息&amp;nbsp;+&amp;nbsp;最近&amp;nbsp;N&amp;nbsp;轮对话&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total&amp;nbsp;=&amp;nbsp;self._estimate_tokens()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while&amp;nbsp;total&amp;nbsp;&amp;gt;&amp;nbsp;self.max_tokens&amp;nbsp;and&amp;nbsp;len(self.messages)&amp;nbsp;&amp;gt;&amp;nbsp;2:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;保留第一条&amp;nbsp;system&amp;nbsp;消息，删除最旧的&amp;nbsp;user/assistant&amp;nbsp;对
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;self.messages[1][&amp;quot;role&amp;quot;]&amp;nbsp;!=&amp;nbsp;&amp;quot;system&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;removed&amp;nbsp;=&amp;nbsp;self.messages.pop(1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total&amp;nbsp;-=&amp;nbsp;self._count_tokens(removed[&amp;quot;content&amp;quot;])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_estimate_tokens(self)&amp;nbsp;-&amp;gt;&amp;nbsp;int:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;sum(len(m[&amp;quot;content&amp;quot;])&amp;nbsp;//&amp;nbsp;3&amp;nbsp;for&amp;nbsp;m&amp;nbsp;in&amp;nbsp;self.messages)&lt;/pre&gt;&lt;p&gt;对于需要长期记忆的 Agent，推荐使用 &lt;strong&gt;Mem0&lt;/strong&gt; 或自建向量存储（如 Qdrant + text-embedding）来持久化重要信息。&lt;/p&gt;&lt;h2&gt;五、错误恢复与容错设计：从 Demo 到生产的关键跨越&lt;/h2&gt;&lt;p&gt;生产环境的 Agent 面临各种故障：网络超时、工具返回错误、模型幻觉、无限循环……不做好容错，Agent 要么卡死，要么产生错误结果。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. 设置最大步骤数&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;class&amp;nbsp;AgentRunner:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;max_steps:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;20):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.max_steps&amp;nbsp;=&amp;nbsp;max_steps
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;async&amp;nbsp;def&amp;nbsp;run(self,&amp;nbsp;task:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;steps&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;messages&amp;nbsp;=&amp;nbsp;[{&amp;quot;role&amp;quot;:&amp;nbsp;&amp;quot;user&amp;quot;,&amp;nbsp;&amp;quot;content&amp;quot;:&amp;nbsp;task}]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while&amp;nbsp;steps&amp;nbsp;&amp;lt;&amp;nbsp;self.max_steps:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;response&amp;nbsp;=&amp;nbsp;await&amp;nbsp;self.llm.call(messages)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;response.finish_reason&amp;nbsp;==&amp;nbsp;&amp;quot;stop&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;response.content&amp;nbsp;&amp;nbsp;#&amp;nbsp;任务完成
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;response.finish_reason&amp;nbsp;==&amp;nbsp;&amp;quot;tool_calls&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tool_results&amp;nbsp;=&amp;nbsp;await&amp;nbsp;self.execute_tools(response.tool_calls)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;messages.extend(tool_results)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;steps&amp;nbsp;+=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;任务超出最大步骤数，已终止&amp;quot;&amp;nbsp;&amp;nbsp;#&amp;nbsp;防止无限循环&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;2. 工具调用重试&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;import&amp;nbsp;asyncio
from&amp;nbsp;tenacity&amp;nbsp;import&amp;nbsp;retry,&amp;nbsp;stop_after_attempt,&amp;nbsp;wait_exponential

@retry(stop=stop_after_attempt(3),&amp;nbsp;wait=wait_exponential(min=1,&amp;nbsp;max=10))
async&amp;nbsp;def&amp;nbsp;call_tool_with_retry(tool_name:&amp;nbsp;str,&amp;nbsp;params:&amp;nbsp;dict):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;await&amp;nbsp;tools[tool_name](**params)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;success&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;result}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;将错误信息返回给模型，让它重新规划
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;success&amp;quot;:&amp;nbsp;False,&amp;nbsp;&amp;quot;error&amp;quot;:&amp;nbsp;str(e),&amp;nbsp;&amp;quot;hint&amp;quot;:&amp;nbsp;&amp;quot;请检查参数后重试&amp;quot;}&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;3. 人工介入点（Human-in-the-Loop）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;对于高风险操作（删除数据、发送邮件、支付），在执行前暂停并请求人工确认：&lt;/p&gt;&lt;pre&gt;HIGH_RISK_TOOLS&amp;nbsp;=&amp;nbsp;{&amp;quot;delete_user&amp;quot;,&amp;nbsp;&amp;quot;send_email&amp;quot;,&amp;nbsp;&amp;quot;process_payment&amp;quot;}

async&amp;nbsp;def&amp;nbsp;execute_tool(tool_name:&amp;nbsp;str,&amp;nbsp;params:&amp;nbsp;dict):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;tool_name&amp;nbsp;in&amp;nbsp;HIGH_RISK_TOOLS:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;confirmed&amp;nbsp;=&amp;nbsp;await&amp;nbsp;request_human_approval(tool_name,&amp;nbsp;params)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;confirmed:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;status&amp;quot;:&amp;nbsp;&amp;quot;cancelled&amp;quot;,&amp;nbsp;&amp;quot;reason&amp;quot;:&amp;nbsp;&amp;quot;用户拒绝授权&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;await&amp;nbsp;tools[tool_name](**params)&lt;/pre&gt;&lt;h2&gt;六、可观测性：让 Agent 的&amp;quot;思考&amp;quot;不再是黑盒&lt;/h2&gt;&lt;p&gt;生产 Agent 必须是可观测的。没有追踪，出了问题你甚至不知道 Agent 到底做了什么。&lt;/p&gt;&lt;p&gt;推荐使用 &lt;strong&gt;LangSmith&lt;/strong&gt;（LangChain 生态）或 &lt;strong&gt;Langfuse&lt;/strong&gt;（开源，自托管友好）进行追踪。核心追踪维度：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Trace&lt;/strong&gt;：完整的 Agent 执行链路，包含所有 LLM 调用和工具调用&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Span&lt;/strong&gt;：单次操作的耗时、输入输出&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token 用量&lt;/strong&gt;：每次 LLM 调用的 prompt/completion tokens，用于成本控制&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;错误率&lt;/strong&gt;：工具调用失败率、模型返回异常率&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;from&amp;nbsp;langfuse&amp;nbsp;import&amp;nbsp;Langfuse
from&amp;nbsp;langfuse.decorators&amp;nbsp;import&amp;nbsp;observe

langfuse&amp;nbsp;=&amp;nbsp;Langfuse()

@observe(name=&amp;quot;agent_run&amp;quot;)
async&amp;nbsp;def&amp;nbsp;run_agent(task:&amp;nbsp;str,&amp;nbsp;user_id:&amp;nbsp;str):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;trace&amp;nbsp;=&amp;nbsp;langfuse.trace(name=&amp;quot;agent_task&amp;quot;,&amp;nbsp;user_id=user_id,&amp;nbsp;input=task)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;trace.span(name=&amp;quot;planning&amp;quot;)&amp;nbsp;as&amp;nbsp;span:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;plan&amp;nbsp;=&amp;nbsp;await&amp;nbsp;llm.plan(task)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;span.end(output=plan)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;step&amp;nbsp;in&amp;nbsp;plan.steps:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;trace.span(name=f&amp;quot;tool_{step.tool}&amp;quot;)&amp;nbsp;as&amp;nbsp;span:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;await&amp;nbsp;execute_tool(step.tool,&amp;nbsp;step.params)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;span.end(output=result,&amp;nbsp;metadata={&amp;quot;tokens&amp;quot;:&amp;nbsp;result.get(&amp;quot;tokens&amp;quot;)})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;final_result&lt;/pre&gt;&lt;p&gt;除了追踪，还要建立 &lt;strong&gt;评估体系（Evaluation）&lt;/strong&gt;。定期用标准测试集跑 Agent，追踪任务完成率、平均步骤数、成本等指标的变化趋势，这样才能知道模型升级或 Prompt 调整是否真的带来了提升。&lt;/p&gt;&lt;h2&gt;七、生产部署的工程实践总结&lt;/h2&gt;&lt;p&gt;把所有经验凝练成几条可直接落地的建议：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;从简单架构开始&lt;/strong&gt;：不要一上来就用多 Agent，单 Agent + 好工具能解决 80% 的问题&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;投资工具质量&lt;/strong&gt;：花在工具描述和错误处理上的时间，比调 Prompt 更值&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;先跑通，再优化&lt;/strong&gt;：先用 GPT-4o 跑通业务逻辑，再考虑换小模型降成本&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;一切都要可追踪&lt;/strong&gt;：没有观测性的 Agent 不要上生产&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;为失败设计&lt;/strong&gt;：工具失败是常态，每个工具都要有明确的错误返回格式&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;控制上下文长度&lt;/strong&gt;：Token 成本会随任务复杂度指数上涨，要主动管理&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;灰度发布&lt;/strong&gt;：先给 5% 用户，观察错误率和完成率，再逐步放量&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;AI Agent 正在经历从&amp;quot;技术演示&amp;quot;到&amp;quot;生产系统&amp;quot;的关键转型期。掌握这些工程实践，才能在这波浪潮中真正建立竞争优势，而不是停留在 Demo 阶段。&lt;/p&gt;</description><pubDate>Wed, 24 Jun 2026 08:08:19 +0800</pubDate></item><item><title>Android Jetpack Compose 性能优化实战：告别卡顿的7个关键技巧</title><link>https://blog.resmic.cn/post/303.html</link><description>&lt;p&gt;&lt;img src=&quot;https://blog.resmic.cn/zb_users/upload/2026/06/20260623080939178217337923665.jpg&quot; alt=&quot;封面&quot; style=&quot;width:100%;&quot;/&gt;&lt;/p&gt;&lt;h2&gt;为什么 Compose 会出现性能问题？&lt;/h2&gt;&lt;p&gt;Jetpack Compose 基于声明式 UI 范式，通过重组（Recomposition）来更新界面。每当状态（State）发生变化时，依赖该状态的可组合函数就会重新执行。理论上 Compose 的智能重组可以跳过未变化的节点，但开发者若不了解其内部机制，很容易写出触发大范围重组的代码。&lt;/p&gt;&lt;p&gt;常见的性能陷阱包括：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;在顶层 Composable 中直接读取频繁变化的状态&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;传入不稳定（Unstable）的参数类型，导致 Compose 无法智能跳过&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;在 LazyColumn 中使用 index 作为 key，造成大量无效重组&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;滥用 remember 或忘记使用 remember，导致重组时重复计算&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;状态提升与最小化重组范围&lt;/h2&gt;&lt;p&gt;状态提升（State Hoisting）是 Compose 官方推荐的模式，核心思路是将状态&amp;quot;上移&amp;quot;到合适的层级，让尽可能少的 Composable 依赖同一个状态。&lt;/p&gt;&lt;pre&gt;//&amp;nbsp;❌&amp;nbsp;不推荐：整个&amp;nbsp;Screen&amp;nbsp;因&amp;nbsp;inputText&amp;nbsp;变化而重组
@Composable
fun&amp;nbsp;SearchScreen()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;inputText&amp;nbsp;by&amp;nbsp;remember&amp;nbsp;{&amp;nbsp;mutableStateOf(&amp;quot;&amp;quot;)&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Column&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SearchBar(text&amp;nbsp;=&amp;nbsp;inputText,&amp;nbsp;onTextChange&amp;nbsp;=&amp;nbsp;{&amp;nbsp;inputText&amp;nbsp;=&amp;nbsp;it&amp;nbsp;})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HeavyResultList()&amp;nbsp;//&amp;nbsp;每次输入都重组！
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

//&amp;nbsp;✅&amp;nbsp;推荐：将&amp;nbsp;inputText&amp;nbsp;状态隔离在&amp;nbsp;SearchBar&amp;nbsp;内部
@Composable
fun&amp;nbsp;SearchScreen()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;query&amp;nbsp;by&amp;nbsp;remember&amp;nbsp;{&amp;nbsp;mutableStateOf(&amp;quot;&amp;quot;)&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Column&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SearchBar(onSearch&amp;nbsp;=&amp;nbsp;{&amp;nbsp;query&amp;nbsp;=&amp;nbsp;it&amp;nbsp;})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HeavyResultList(query&amp;nbsp;=&amp;nbsp;query)&amp;nbsp;//&amp;nbsp;只在搜索触发时重组
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;p&gt;通过合理的状态提升，可以将重组范围从整个屏幕缩减到局部组件，显著提升流畅度。&lt;/p&gt;&lt;h2&gt;derivedStateOf：避免无效重组的利器&lt;/h2&gt;&lt;p&gt;当一个状态需要从另一个状态派生时，直接读取原始状态会导致每次变化都触发重组，而实际上派生结果可能并没有改变。&lt;code&gt;derivedStateOf&lt;/code&gt; 可以解决这个问题。&lt;/p&gt;&lt;pre&gt;//&amp;nbsp;❌&amp;nbsp;不推荐：listState&amp;nbsp;每次滚动都触发按钮重组
val&amp;nbsp;showBackToTop&amp;nbsp;=&amp;nbsp;listState.firstVisibleItemIndex&amp;nbsp;&amp;gt;&amp;nbsp;0

//&amp;nbsp;✅&amp;nbsp;推荐：只有跨越阈值时才触发重组
val&amp;nbsp;showBackToTop&amp;nbsp;by&amp;nbsp;remember&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;derivedStateOf&amp;nbsp;{&amp;nbsp;listState.firstVisibleItemIndex&amp;nbsp;&amp;gt;&amp;nbsp;0&amp;nbsp;}
}

//&amp;nbsp;在&amp;nbsp;LazyColumn&amp;nbsp;中的典型用法
@Composable
fun&amp;nbsp;ChatList(messages:&amp;nbsp;List)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;listState&amp;nbsp;=&amp;nbsp;rememberLazyListState()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;showFab&amp;nbsp;by&amp;nbsp;remember&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;derivedStateOf&amp;nbsp;{&amp;nbsp;listState.firstVisibleItemIndex&amp;nbsp;&amp;gt;&amp;nbsp;5&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Box&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LazyColumn(state&amp;nbsp;=&amp;nbsp;listState)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items(messages,&amp;nbsp;key&amp;nbsp;=&amp;nbsp;{&amp;nbsp;it.id&amp;nbsp;})&amp;nbsp;{&amp;nbsp;msg&amp;nbsp;-&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MessageItem(msg)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(showFab)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FloatingActionButton(onClick&amp;nbsp;=&amp;nbsp;{&amp;nbsp;/*&amp;nbsp;scroll&amp;nbsp;to&amp;nbsp;bottom&amp;nbsp;*/&amp;nbsp;})&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Icon(Icons.Default.ArrowDownward,&amp;nbsp;contentDescription&amp;nbsp;=&amp;nbsp;null)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;h2&gt;LazyColumn 性能优化：key 与 contentType&lt;/h2&gt;&lt;p&gt;LazyColumn 是 Compose 中最常用也最容易出现性能问题的组件。正确使用 &lt;code&gt;key&lt;/code&gt; 和 &lt;code&gt;contentType&lt;/code&gt; 参数对性能至关重要。&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;key 参数&lt;/strong&gt;：为每个 item 提供稳定唯一的标识符，帮助 Compose 在列表变化时复用已有节点，避免全量重组&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;contentType 参数&lt;/strong&gt;：当列表中存在多种类型的 item 时，相同 contentType 的 item 可以复用视图层，提升滚动性能&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;LazyColumn&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;items&amp;nbsp;=&amp;nbsp;feedItems,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;key&amp;nbsp;=&amp;nbsp;{&amp;nbsp;item&amp;nbsp;-&amp;gt;&amp;nbsp;item.id&amp;nbsp;},&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;稳定&amp;nbsp;key
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;contentType&amp;nbsp;=&amp;nbsp;{&amp;nbsp;item&amp;nbsp;-&amp;gt;&amp;nbsp;item.type&amp;nbsp;}&amp;nbsp;//&amp;nbsp;区分内容类型
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&amp;nbsp;{&amp;nbsp;item&amp;nbsp;-&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when&amp;nbsp;(item.type)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FeedType.POST&amp;nbsp;-&amp;gt;&amp;nbsp;PostCard(item)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FeedType.AD&amp;nbsp;-&amp;gt;&amp;nbsp;AdBanner(item)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FeedType.STORY&amp;nbsp;-&amp;gt;&amp;nbsp;StoryRow(item)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;p&gt;另外，在 item 内部避免使用 lambda 直接计算复杂逻辑，应提前用 remember 缓存：&lt;/p&gt;&lt;pre&gt;//&amp;nbsp;❌&amp;nbsp;每次重组都重新计算
@Composable
fun&amp;nbsp;PostCard(post:&amp;nbsp;Post)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;formattedDate&amp;nbsp;=&amp;nbsp;formatDate(post.createdAt)&amp;nbsp;//&amp;nbsp;每次重组都调用
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Text(formattedDate)
}

//&amp;nbsp;✅&amp;nbsp;缓存计算结果
@Composable
fun&amp;nbsp;PostCard(post:&amp;nbsp;Post)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val&amp;nbsp;formattedDate&amp;nbsp;=&amp;nbsp;remember(post.createdAt)&amp;nbsp;{&amp;nbsp;formatDate(post.createdAt)&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Text(formattedDate)
}&lt;/pre&gt;&lt;h2&gt;使用工具定位性能瓶颈&lt;/h2&gt;&lt;p&gt;Android Studio 提供了多款工具帮助定位 Compose 性能问题：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Layout Inspector&lt;/strong&gt;：在 Android Studio 菜单 View → Tool Windows → Layout Inspector 中打开，可实时查看 Compose 节点树，观察哪些组件正在重组&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Recomposition Highlighter&lt;/strong&gt;：在 Layout Inspector 中勾选 &amp;quot;Show recomposition counts&amp;quot;，重组次数高的组件会高亮显示，快速定位热点&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compose Compiler Metrics&lt;/strong&gt;：在 build.gradle 中开启编译指标，输出每个 Composable 的稳定性报告&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;//&amp;nbsp;build.gradle.kts&amp;nbsp;(app&amp;nbsp;module)
android&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;kotlinOptions&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;freeCompilerArgs&amp;nbsp;+=&amp;nbsp;listOf(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;-P&amp;quot;,&amp;nbsp;&amp;quot;plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${project.buildDir.absolutePath}/compose_metrics&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;-P&amp;quot;,&amp;nbsp;&amp;quot;plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=${project.buildDir.absolutePath}/compose_metrics&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/pre&gt;&lt;p&gt;编译后查看生成的 &lt;code&gt;*-composables.txt&lt;/code&gt; 文件，其中标记为 &lt;code&gt;unstable&lt;/code&gt; 的参数类型就是重组无法跳过的根因，针对性地将其改为 &lt;code&gt;@Stable&lt;/code&gt; 或 &lt;code&gt;@Immutable&lt;/code&gt; 数据类即可解决。&lt;/p&gt;&lt;p&gt;通过以上优化手段的综合运用，可以将 Compose 界面的重组次数减少 60%~80%，帧率稳定在 60fps 以上，带来丝滑流畅的用户体验。&lt;/p&gt;</description><pubDate>Tue, 23 Jun 2026 08:10:19 +0800</pubDate></item><item><title>大模型推理增强实战：CoT、ToT 与 R1 的原理和应用</title><link>https://blog.resmic.cn/post/302.html</link><description>&lt;p&gt;&lt;img src=&quot;https://blog.resmic.cn/zb_users/upload/2026/06/20260621080406178200024670535.jpg&quot; alt=&quot;封面&quot; style=&quot;width:100%;&quot;/&gt;&lt;/p&gt;&lt;h2&gt;什么是 LLM 推理增强？&lt;/h2&gt;&lt;p&gt;大语言模型（LLM）在自然语言理解方面表现出色，但在面对多步骤逻辑推理、数学计算或复杂规划任务时，普通的&amp;quot;一步到位&amp;quot;生成策略往往表现欠佳。推理增强（Reasoning Enhancement）技术通过引导模型在给出最终答案之前，先输出中间思考步骤，从而大幅提升复杂任务的准确率。&lt;/p&gt;&lt;p&gt;近两年，从 OpenAI 的 o1/o3 系列，到 DeepSeek-R1、Qwen-QwQ，再到 Google 的 Gemini Thinking，&amp;quot;慢思考&amp;quot;已成为前沿 AI 模型的核心竞争力之一。理解这些技术背后的原理，对开发者在实际应用中选型和落地至关重要。&lt;/p&gt;&lt;h2&gt;Chain-of-Thought（CoT）思维链&lt;/h2&gt;&lt;p&gt;思维链提示（Chain-of-Thought Prompting）由 Google Brain 团队于 2022 年提出，核心思想是在 few-shot 示例中加入中间推理步骤，引导模型&amp;quot;一步一步地思考&amp;quot;。&lt;/p&gt;&lt;p&gt;最简单的 CoT 提示只需在示例答案前加上推理过程：&lt;/p&gt;&lt;pre&gt;问题：小明有&amp;nbsp;5&amp;nbsp;个苹果，送给小红&amp;nbsp;2&amp;nbsp;个后，又买了&amp;nbsp;3&amp;nbsp;个，现在有几个？
思考：小明先有&amp;nbsp;5&amp;nbsp;个，送出&amp;nbsp;2&amp;nbsp;个剩&amp;nbsp;3&amp;nbsp;个，再买&amp;nbsp;3&amp;nbsp;个共&amp;nbsp;6&amp;nbsp;个。
答案：6&amp;nbsp;个&lt;/pre&gt;&lt;p&gt;研究表明，CoT 在 GPT-3 等大参数模型上效果显著，对于小模型提升有限。常见变体包括：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zero-shot CoT&lt;/strong&gt;：只需在提示末尾加 &amp;quot;Let&amp;#39;s think step by step&amp;quot;，无需示例&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Self-consistency&lt;/strong&gt;：多次采样取多数答案，提升稳定性&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Least-to-Most&lt;/strong&gt;：将复杂问题拆解为子问题，逐步求解&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Tree of Thoughts（ToT）：树状探索&lt;/h2&gt;&lt;p&gt;思维树（Tree of Thoughts）将问题求解建模为搜索树，每个节点是一个&amp;quot;思维步骤&amp;quot;，模型可以在多个分支间评估并回溯，类似于人类在解决难题时的试错过程。&lt;/p&gt;&lt;p&gt;ToT 的基本流程如下：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;生成（Generate）&lt;/strong&gt;：从当前状态出发，生成多个候选下一步&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;评估（Evaluate）&lt;/strong&gt;：让模型对每个候选步骤打分或判断可行性&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;搜索（Search）&lt;/strong&gt;：使用 BFS 或 DFS 策略选择最优路径&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;#&amp;nbsp;伪代码示意
def&amp;nbsp;tree_of_thoughts(problem,&amp;nbsp;depth=3,&amp;nbsp;branching=3):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;root&amp;nbsp;=&amp;nbsp;ThoughtNode(problem)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;_&amp;nbsp;in&amp;nbsp;range(depth):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;candidates&amp;nbsp;=&amp;nbsp;generate_thoughts(root,&amp;nbsp;n=branching)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scores&amp;nbsp;=&amp;nbsp;evaluate_thoughts(candidates)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;root&amp;nbsp;=&amp;nbsp;max(candidates,&amp;nbsp;key=lambda&amp;nbsp;x:&amp;nbsp;scores[x])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;root.solution&lt;/pre&gt;&lt;p&gt;ToT 在 24 点游戏、创意写作规划等任务上比标准 CoT 提升显著，代价是推理耗时和 token 消耗成倍增加。&lt;/p&gt;&lt;h2&gt;o1/R1：强化学习驱动的深度推理&lt;/h2&gt;&lt;p&gt;OpenAI o1 和 DeepSeek-R1 代表了推理增强的另一条路线：通过大规模强化学习（RL），让模型在训练阶段就内化长链推理能力，而非依赖提示工程。&lt;/p&gt;&lt;p&gt;DeepSeek-R1 的训练流程值得重点关注：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;冷启动（Cold Start）&lt;/strong&gt;：用少量高质量 CoT 数据微调基座模型，建立推理格式&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;GRPO 强化学习&lt;/strong&gt;：以答案正确性为奖励信号，让模型自主探索更长、更优的推理路径&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;蒸馏（Distillation）&lt;/strong&gt;：将 R1 的推理能力迁移到 7B/14B 等小模型，大幅降低部署成本&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;与 o1 类似，这类模型会在输出最终答案前生成大量&amp;quot;thinking tokens&amp;quot;，这些 token 对用户不可见，但对推理质量至关重要。&lt;/p&gt;&lt;h2&gt;实战：如何在应用中使用推理模型&lt;/h2&gt;&lt;p&gt;对于开发者而言，选择合适的推理增强策略需要权衡精度、延迟和成本三个维度。以下是一些实用建议：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;轻量任务&lt;/strong&gt;（问答、摘要）：普通模型 + Zero-shot CoT 即可，无需额外开销&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;中等复杂度&lt;/strong&gt;（代码生成、多步推理）：使用 DeepSeek-R1-Distill-7B 或 Qwen3-8B（thinking 模式），本地可部署&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;高复杂度&lt;/strong&gt;（数学竞赛、科学问题）：调用 o3-mini 或 DeepSeek-R1 API，接受更高延迟&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;from&amp;nbsp;openai&amp;nbsp;import&amp;nbsp;OpenAI

client&amp;nbsp;=&amp;nbsp;OpenAI(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;api_key=&amp;quot;your-api-key&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;base_url=&amp;quot;https://api.deepseek.com&amp;quot;
)

response&amp;nbsp;=&amp;nbsp;client.chat.completions.create(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;model=&amp;quot;deepseek-reasoner&amp;quot;,&amp;nbsp;&amp;nbsp;#&amp;nbsp;R1&amp;nbsp;模型
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;messages=[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;quot;role&amp;quot;:&amp;nbsp;&amp;quot;user&amp;quot;,&amp;nbsp;&amp;quot;content&amp;quot;:&amp;nbsp;&amp;quot;证明：√2&amp;nbsp;是无理数&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]
)

#&amp;nbsp;reasoning_content&amp;nbsp;包含思维链
print(response.choices[0].message.reasoning_content)
#&amp;nbsp;content&amp;nbsp;是最终答案
print(response.choices[0].message.content)&lt;/pre&gt;&lt;p&gt;此外，对于需要精确控制推理过程的场景，可以考虑使用 &lt;strong&gt;LangGraph&lt;/strong&gt; 或 &lt;strong&gt;DSPy&lt;/strong&gt; 框架，将 CoT、ToT 等策略模块化，方便评估和迭代优化。&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Mon, 22 Jun 2026 08:06:12 +0800</pubDate></item><item><title>PHP 8.4 全新特性深度解析：属性钩子、不对称可见性与新数组函数实战指南</title><link>https://blog.resmic.cn/post/301.html</link><description>&lt;p&gt;&lt;img src=&quot;https://blog.resmic.cn/zb_users/upload/2026/06/20260621080406178200024670535.jpg&quot; alt=&quot;封面&quot; style=&quot;width:100%;&quot;&gt;&lt;/p&gt;

&lt;h2&gt;PHP 8.4 概览：为什么这是近年来最重要的版本&lt;/h2&gt;
&lt;p&gt;PHP 8.4 于 2024 年 11 月正式发布，带来了自 PHP 8.0 以来最具颠覆性的语法与功能更新。无论你是独立开发者、Laravel/Symfony 用户，还是维护大型 PHP 系统的架构师，这次升级都值得认真对待。&lt;/p&gt;
&lt;p&gt;本文将逐一拆解 PHP 8.4 的核心新特性，并结合真实代码示例，帮助你快速上手并做好生产环境迁移准备。&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;属性钩子（Property Hooks）：告别冗余的 getter/setter&lt;/li&gt;
  &lt;li&gt;不对称可见性（Asymmetric Visibility）：细粒度访问控制&lt;/li&gt;
  &lt;li&gt;全新数组函数：array_find、array_find_key 等&lt;/li&gt;
  &lt;li&gt;new 表达式无需括号即可链式调用&lt;/li&gt;
  &lt;li&gt;性能提升与 JIT 优化&lt;/li&gt;
  &lt;li&gt;弃用与向后不兼容变更&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;属性钩子（Property Hooks）：革命性的 getter/setter 替代方案&lt;/h2&gt;
&lt;p&gt;属性钩子是 PHP 8.4 最受关注的新特性之一。它允许在类属性声明处直接内联 get/set 逻辑，彻底消除传统 getter/setter 方法的样板代码。&lt;/p&gt;
&lt;p&gt;传统写法（PHP 8.3 及以前）：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;class User {
    private string $_name;

    public function getName(): string {
        return $this-&gt;_name;
    }

    public function setName(string $value): void {
        if (empty(trim($value))) {
            throw new \InvalidArgumentException('名称不能为空');
        }
        $this-&gt;_name = trim($value);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PHP 8.4 属性钩子写法：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;class User {
    public string $name {
        get =&gt; $this-&gt;name;
        set {
            if (empty(trim($value))) {
                throw new \InvalidArgumentException('名称不能为空');
            }
            $this-&gt;name = trim($value);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;属性钩子支持只读（只定义 get）、只写（只定义 set）或读写双钩子。与接口结合使用时，接口中声明的属性钩子签名会被子类继承和实现，进一步提升代码契约能力。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;interface HasFullName {
    public string $fullName { get; }
}

class Person implements HasFullName {
    public string $fullName {
        get =&gt; &quot;{$this-&gt;firstName} {$this-&gt;lastName}&quot;;
    }

    public function __construct(
        public string $firstName,
        public string $lastName
    ) {}
}&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;不对称可见性（Asymmetric Visibility）&lt;/h2&gt;
&lt;p&gt;PHP 8.4 引入了不对称可见性语法，允许对同一属性的读取和写入设置不同的访问级别。这在构建只读 API 对象、值对象（Value Object）时极为实用。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;class Order {
    public private(set) int $status = 0;
    public protected(set) string $trackingNumber = '';

    public function ship(string $tracking): void {
        $this-&gt;status = 1;
        $this-&gt;trackingNumber = $tracking;
    }
}

$order = new Order();
echo $order-&gt;status;         // ✅ public 可读
$order-&gt;status = 2;          // ❌ 报错：只能在类内部写入&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;支持的可见性组合：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;public private(set)&lt;/code&gt;：公开读，私有写&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;public protected(set)&lt;/code&gt;：公开读，受保护写&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;protected private(set)&lt;/code&gt;：受保护读，私有写&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;该特性与 PHP 8.1 的 &lt;code&gt;readonly&lt;/code&gt; 属性形成互补——readonly 只能写一次，而不对称可见性允许多次写入但限制外部访问。&lt;/p&gt;

&lt;h2&gt;全新数组函数：array_find、array_find_key、array_any、array_all&lt;/h2&gt;
&lt;p&gt;PHP 8.4 新增了四个期待已久的数组函数，让常见的数组搜索和断言操作更加语义化，无需再手写 foreach 循环。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;$users = [
    ['id' =&gt; 1, 'name' =&gt; 'Alice', 'age' =&gt; 28],
    ['id' =&gt; 2, 'name' =&gt; 'Bob',   'age' =&gt; 35],
    ['id' =&gt; 3, 'name' =&gt; 'Carol', 'age' =&gt; 22],
];

// array_find：找到第一个满足条件的元素
$adult = array_find($users, fn($u) =&gt; $u['age'] &gt;= 30);
// ['id' =&gt; 2, 'name' =&gt; 'Bob', 'age' =&gt; 35]

// array_find_key：找到第一个满足条件的键名
$key = array_find_key($users, fn($u) =&gt; $u['name'] === 'Carol');
// 2

// array_any：任一元素满足条件返回 true
$hasMinor = array_any($users, fn($u) =&gt; $u['age'] &lt; 18);
// false

// array_all：所有元素满足条件返回 true
$allAdults = array_all($users, fn($u) =&gt; $u['age'] &gt;= 18);
// true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这些函数都接受回调作为第二个参数，语义清晰，可以有效替代 &lt;code&gt;array_filter&lt;/code&gt; + &lt;code&gt;reset&lt;/code&gt; 的组合写法。&lt;/p&gt;

&lt;h2&gt;new 表达式无需括号即可链式调用&lt;/h2&gt;
&lt;p&gt;在 PHP 8.3 及更早版本中，如果想在 &lt;code&gt;new&lt;/code&gt; 创建的对象上立即调用方法，需要用括号包裹才能链式调用。PHP 8.4 移除了这一限制。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;// PHP 8.3（需要括号）
$result = (new QueryBuilder())
    -&gt;table('users')
    -&gt;where('active', 1)
    -&gt;get();

// PHP 8.4（无需括号，更简洁）
$result = new QueryBuilder()
    -&gt;table('users')
    -&gt;where('active', 1)
    -&gt;get();

// 静态属性和常量访问同样支持
$version = new App()-&gt;version;
$const = new Config()::DEFAULT_TIMEOUT;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这一改变看似微小，但在链式 Builder 模式、Fluent Interface 设计中能显著提升代码可读性。&lt;/p&gt;

&lt;h2&gt;性能提升：JIT 优化与内存占用降低&lt;/h2&gt;
&lt;p&gt;PHP 8.4 对 JIT（即时编译）引擎进行了重构，引入了新的 IR（中间表示）框架，使编译后的机器码质量更高。根据官方基准测试：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;计算密集型任务（如数学运算、字符串处理）速度提升约 &lt;strong&gt;15-20%&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;典型 Web 应用场景（Laravel、Symfony）提升约 &lt;strong&gt;5-10%&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;内存占用在 long-running 进程中降低约 &lt;strong&gt;10%&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;启用 JIT 的推荐配置（php.ini）：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;opcache.enable=1
opcache.jit=tracing
opcache.jit_buffer_size=128M&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：如果你使用 Swoole/RoadRunner 等常驻内存框架，JIT 带来的收益会更加明显。&lt;/p&gt;

&lt;h2&gt;弃用项与升级迁移指南&lt;/h2&gt;
&lt;p&gt;升级前需要关注以下弃用变更，避免影响线上服务：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;隐式可空类型参数弃用&lt;/strong&gt;：&lt;code&gt;function foo(string $x = null)&lt;/code&gt; 需改为 &lt;code&gt;function foo(?string $x = null)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;GMP 对象使用 == 比较弃用&lt;/strong&gt;：应使用 &lt;code&gt;gmp_cmp()&lt;/code&gt; 函数&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;IMAP、OCI8、PDO_OCI 等扩展移至 PECL&lt;/strong&gt;：需单独安装&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;MySQLi 部分函数弃用&lt;/strong&gt;：&lt;code&gt;mysqli_ping()&lt;/code&gt;、&lt;code&gt;mysqli_kill()&lt;/code&gt; 等建议迁移&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;推荐的升级流程：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 1. 在测试环境安装 PHP 8.4
sudo apt install php8.4 php8.4-cli php8.4-fpm php8.4-mbstring php8.4-xml

# 2. 使用 php-cs-fixer 检查兼容性
composer require --dev friendsofphp/php-cs-fixer
vendor/bin/php-cs-fixer fix --dry-run --diff

# 3. 运行静态分析
composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse --level=8 src/

# 4. 执行完整测试套件
./vendor/bin/phpunit --stop-on-failure&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PHP 8.4 是一次向好的进化，属性钩子和不对称可见性让面向对象编程更加优雅，新数组函数提升了日常开发效率，JIT 优化带来了实质性的性能收益。建议开发团队尽快在测试环境验证兼容性，为年底前的生产环境升级做好准备。&lt;/p&gt;
</description><pubDate>Sun, 21 Jun 2026 08:04:26 +0800</pubDate></item><item><title>PHP 8.4 新特性深度解析：属性钩子与懒加载对象实战</title><link>https://blog.resmic.cn/post/300.html</link><description>&lt;p&gt;&lt;img src=&quot;https://blog.resmic.cn/zb_users/upload/2026/06/20260620080932178191417213433.jpg&quot; alt=&quot;封面&quot; style=&quot;width:100%;&quot;/&gt;&lt;/p&gt;&lt;h2&gt;PHP 8.4 概览：为什么值得关注？&lt;/h2&gt;&lt;p&gt;PHP 8.4 于 2024 年 11 月正式发布，是 PHP 8.x 系列中迄今为止改进最为深远的版本之一。在性能、语法糖和面向对象编程模型上都带来了重大突破。如果你还在使用 PHP 8.1 或 8.2，那么升级到 8.4 将会让你的代码更简洁、更高效。&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;属性钩子（Property Hooks）：告别繁琐的 getter/setter&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;懒加载对象（Lazy Objects）：延迟初始化，提升性能&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;全新 HTML5 解析器：基于 Lexbor，符合 W3C 标准&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;数组函数扩展：array_find()、array_find_key() 等新函数&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;PDO 新驱动：mysqlnd 整合更深入&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;属性钩子（Property Hooks）详解&lt;/h2&gt;&lt;p&gt;属性钩子是 PHP 8.4 最重磅的特性，它允许你直接在属性声明上定义 get 和 set 逻辑，无需额外的 getter/setter 方法，大幅简化面向对象代码。&lt;/p&gt;&lt;pre&gt;&amp;lt;?php
class&amp;nbsp;User&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;string&amp;nbsp;$name&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get&amp;nbsp;=&amp;gt;&amp;nbsp;strtoupper($this-&amp;gt;name);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set(string&amp;nbsp;$value)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(strlen($value)&amp;nbsp;&amp;lt;&amp;nbsp;2)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw&amp;nbsp;new&amp;nbsp;\ValueError(&amp;quot;Name&amp;nbsp;must&amp;nbsp;be&amp;nbsp;at&amp;nbsp;least&amp;nbsp;2&amp;nbsp;characters&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;name&amp;nbsp;=&amp;nbsp;trim($value);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;string&amp;nbsp;$email&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get&amp;nbsp;=&amp;gt;&amp;nbsp;$this-&amp;gt;email;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set(string&amp;nbsp;$value)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!filter_var($value,&amp;nbsp;FILTER_VALIDATE_EMAIL))&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw&amp;nbsp;new&amp;nbsp;\ValueError(&amp;quot;Invalid&amp;nbsp;email&amp;nbsp;address&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;email&amp;nbsp;=&amp;nbsp;strtolower($value);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;__construct(string&amp;nbsp;$name,&amp;nbsp;string&amp;nbsp;$email)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;name&amp;nbsp;=&amp;nbsp;$name;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;email&amp;nbsp;=&amp;nbsp;$email;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

$user&amp;nbsp;=&amp;nbsp;new&amp;nbsp;User(&amp;quot;&amp;nbsp;&amp;nbsp;Alice&amp;nbsp;&amp;nbsp;&amp;quot;,&amp;nbsp;&amp;quot;Alice@Example.COM&amp;quot;);
echo&amp;nbsp;$user-&amp;gt;name;&amp;nbsp;&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;ALICE（自动&amp;nbsp;trim&amp;nbsp;+&amp;nbsp;uppercase）
echo&amp;nbsp;$user-&amp;gt;email;&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;alice@example.com（自动&amp;nbsp;lowercase）&lt;/pre&gt;&lt;p&gt;属性钩子支持只读钩子、继承覆盖，以及接口中声明钩子契约，让代码的语义表达更加清晰。&lt;/p&gt;&lt;h2&gt;懒加载对象（Lazy Objects）&lt;/h2&gt;&lt;p&gt;懒加载对象（Lazy Objects）让你能够创建一个对象的&amp;quot;占位符&amp;quot;，只有在真正访问其属性或方法时才进行初始化。这对于依赖注入容器、ORM 和代理模式特别有价值。&lt;/p&gt;&lt;pre&gt;&amp;lt;?php
class&amp;nbsp;DatabaseConnection&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;__construct(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;string&amp;nbsp;$host,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;int&amp;nbsp;$port,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;string&amp;nbsp;$dbName
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;模拟耗时的数据库连接
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo&amp;nbsp;&amp;quot;Connecting&amp;nbsp;to&amp;nbsp;{$host}:{$port}/{$dbName}...\n&amp;quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sleep(1);&amp;nbsp;//&amp;nbsp;实际场景中是真实连接
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;query(string&amp;nbsp;$sql):&amp;nbsp;array&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;[];&amp;nbsp;//&amp;nbsp;模拟查询
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

//&amp;nbsp;使用反射&amp;nbsp;API&amp;nbsp;创建懒加载对象
$reflector&amp;nbsp;=&amp;nbsp;new&amp;nbsp;ReflectionClass(DatabaseConnection::class);

$lazyDb&amp;nbsp;=&amp;nbsp;$reflector-&amp;gt;newLazyGhost(function(DatabaseConnection&amp;nbsp;$db)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;只有当&amp;nbsp;$lazyDb&amp;nbsp;被真正使用时才调用
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;__construct(&amp;#39;localhost&amp;#39;,&amp;nbsp;3306,&amp;nbsp;&amp;#39;myapp&amp;#39;);
});

echo&amp;nbsp;&amp;quot;Object&amp;nbsp;created&amp;nbsp;(no&amp;nbsp;connection&amp;nbsp;yet)\n&amp;quot;;

//&amp;nbsp;只有此时才真正建立连接
$result&amp;nbsp;=&amp;nbsp;$lazyDb-&amp;gt;query(&amp;quot;SELECT&amp;nbsp;*&amp;nbsp;FROM&amp;nbsp;users&amp;quot;);
echo&amp;nbsp;&amp;quot;Query&amp;nbsp;executed\n&amp;quot;;&lt;/pre&gt;&lt;p&gt;PHP 8.4 提供两种懒加载方式：&lt;strong&gt;Ghost 对象&lt;/strong&gt;（直接初始化实例）和&lt;strong&gt;Virtual 代理&lt;/strong&gt;（使用独立初始化器返回完整对象）。两者各有适用场景，可根据业务需求选择。&lt;/p&gt;&lt;h2&gt;新增数组函数：array_find() 系列&lt;/h2&gt;&lt;p&gt;PHP 8.4 新增了 4 个实用的数组函数，弥补了长期以来需要用 array_filter + reset 组合才能实现&amp;quot;查找第一个匹配元素&amp;quot;的痛点。&lt;/p&gt;&lt;pre&gt;&amp;lt;?php
$users&amp;nbsp;=&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&amp;#39;id&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;1,&amp;nbsp;&amp;#39;name&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;Alice&amp;#39;,&amp;nbsp;&amp;#39;role&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;admin&amp;#39;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&amp;#39;id&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;2,&amp;nbsp;&amp;#39;name&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;Bob&amp;#39;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;role&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;user&amp;#39;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&amp;#39;id&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;3,&amp;nbsp;&amp;#39;name&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;Carol&amp;#39;,&amp;nbsp;&amp;#39;role&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;admin&amp;#39;],
];

//&amp;nbsp;array_find():&amp;nbsp;找到第一个满足条件的元素
$firstAdmin&amp;nbsp;=&amp;nbsp;array_find($users,&amp;nbsp;fn($u)&amp;nbsp;=&amp;gt;&amp;nbsp;$u[&amp;#39;role&amp;#39;]&amp;nbsp;===&amp;nbsp;&amp;#39;admin&amp;#39;);
//&amp;nbsp;[&amp;#39;id&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;1,&amp;nbsp;&amp;#39;name&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;Alice&amp;#39;,&amp;nbsp;&amp;#39;role&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;admin&amp;#39;]

//&amp;nbsp;array_find_key():&amp;nbsp;找到第一个满足条件的键
$key&amp;nbsp;=&amp;nbsp;array_find_key($users,&amp;nbsp;fn($u)&amp;nbsp;=&amp;gt;&amp;nbsp;$u[&amp;#39;name&amp;#39;]&amp;nbsp;===&amp;nbsp;&amp;#39;Bob&amp;#39;);
//&amp;nbsp;1

//&amp;nbsp;array_any():&amp;nbsp;是否有至少一个元素满足条件
$hasAdmin&amp;nbsp;=&amp;nbsp;array_any($users,&amp;nbsp;fn($u)&amp;nbsp;=&amp;gt;&amp;nbsp;$u[&amp;#39;role&amp;#39;]&amp;nbsp;===&amp;nbsp;&amp;#39;admin&amp;#39;);
//&amp;nbsp;true

//&amp;nbsp;array_all():&amp;nbsp;是否所有元素都满足条件
$allAdmins&amp;nbsp;=&amp;nbsp;array_all($users,&amp;nbsp;fn($u)&amp;nbsp;=&amp;gt;&amp;nbsp;$u[&amp;#39;role&amp;#39;]&amp;nbsp;===&amp;nbsp;&amp;#39;admin&amp;#39;);
//&amp;nbsp;false

echo&amp;nbsp;&amp;quot;First&amp;nbsp;admin:&amp;nbsp;&amp;quot;&amp;nbsp;.&amp;nbsp;$firstAdmin[&amp;#39;name&amp;#39;]&amp;nbsp;.&amp;nbsp;&amp;quot;\n&amp;quot;;&amp;nbsp;//&amp;nbsp;Alice
echo&amp;nbsp;&amp;quot;Bob&amp;#39;s&amp;nbsp;key:&amp;nbsp;$key\n&amp;quot;;&amp;nbsp;//&amp;nbsp;1
echo&amp;nbsp;&amp;quot;Has&amp;nbsp;admin:&amp;nbsp;&amp;quot;&amp;nbsp;.&amp;nbsp;($hasAdmin&amp;nbsp;?&amp;nbsp;&amp;#39;yes&amp;#39;&amp;nbsp;:&amp;nbsp;&amp;#39;no&amp;#39;)&amp;nbsp;.&amp;nbsp;&amp;quot;\n&amp;quot;;&amp;nbsp;//&amp;nbsp;yes&lt;/pre&gt;&lt;p&gt;这 4 个函数让代码更具可读性，同时也避免了 &lt;code&gt;array_filter&lt;/code&gt; 总是返回数组而非单个元素的尴尬。&lt;/p&gt;&lt;h2&gt;升级建议与兼容性注意事项&lt;/h2&gt;&lt;p&gt;PHP 8.4 在保持向后兼容的同时，也做了一些弃用处理，升级前需要注意：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;弃用隐式可为 null 参数&lt;/strong&gt;：&lt;code&gt;function foo(string $s = null)&lt;/code&gt; 需改为 &lt;code&gt;?string $s = null&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;弃用 GMP 对象的隐式转换&lt;/strong&gt;：部分 GMP 函数行为有变化&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;HTML5 解析器&lt;/strong&gt;：&lt;code&gt;DOMDocument::loadHTML()&lt;/code&gt; 底层已替换为 Lexbor，极少数 edge case 输出可能不同&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;推荐工具&lt;/strong&gt;：使用 &lt;code&gt;phpstan/php-8-migration&lt;/code&gt; 或 Rector 自动迁移代码&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;#&amp;nbsp;使用&amp;nbsp;Rector&amp;nbsp;自动升级到&amp;nbsp;PHP&amp;nbsp;8.4&amp;nbsp;兼容
composer&amp;nbsp;require&amp;nbsp;--dev&amp;nbsp;rector/rector
./vendor/bin/rector&amp;nbsp;process&amp;nbsp;src&amp;nbsp;--set-list&amp;nbsp;php84&lt;/pre&gt;&lt;p&gt;总体来说，PHP 8.4 的升级路径非常平滑。属性钩子和懒加载对象的引入，标志着 PHP 正在向更现代化的语言设计迈进。建议在新项目中立即采用，旧项目则可通过 Rector 逐步迁移。&lt;/p&gt;</description><pubDate>Sat, 20 Jun 2026 08:09:49 +0800</pubDate></item><item><title>PHP 8.4 新特性实战：属性钩子与新数组函数详解</title><link>https://blog.resmic.cn/post/299.html</link><description>&lt;p&gt;&lt;img src=&quot;https://blog.resmic.cn/zb_users/upload/2026/06/20260619080831178182771191596.jpg&quot; alt=&quot;封面&quot; style=&quot;width:100%;&quot;/&gt;&lt;/p&gt;&lt;h2&gt;PHP 8.4 概览：为什么值得升级&lt;/h2&gt;&lt;p&gt;PHP 8.4 于 2024 年 11 月正式发布，带来了多项令人期待的语言特性改进。其中最受社区关注的包括&lt;strong&gt;属性钩子（Property Hooks）&lt;/strong&gt;、新增的 &lt;code&gt;array_find()&lt;/code&gt; 系列函数、&lt;code&gt;new&lt;/code&gt; 表达式无需括号调用方法等。这些特性不仅提升了代码的表达能力，也让 PHP 的面向对象编程更加优雅。&lt;/p&gt;&lt;p&gt;本文将通过实战代码逐一讲解这些核心新特性，帮助你在实际项目中快速落地 PHP 8.4。&lt;/p&gt;&lt;h2&gt;属性钩子（Property Hooks）：告别冗余的 getter/setter&lt;/h2&gt;&lt;p&gt;属性钩子是 PHP 8.4 中最重磅的新特性之一。在此之前，为了控制属性的读写行为，我们不得不编写大量重复的 getter 和 setter 方法。PHP 8.4 引入了类似 C# 的属性钩子语法，让代码更加简洁。&lt;/p&gt;&lt;p&gt;属性钩子分为两种：&lt;code&gt;get&lt;/code&gt; 钩子用于控制读取行为，&lt;code&gt;set&lt;/code&gt; 钩子用于控制写入行为。&lt;/p&gt;&lt;pre&gt;&amp;lt;?php

class&amp;nbsp;User&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;string&amp;nbsp;$name&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get&amp;nbsp;=&amp;gt;&amp;nbsp;strtoupper($this-&amp;gt;name);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set(string&amp;nbsp;$value)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(strlen($value)&amp;nbsp;&amp;lt;&amp;nbsp;2)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw&amp;nbsp;new&amp;nbsp;\ValueError(&amp;#39;用户名至少需要2个字符&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;name&amp;nbsp;=&amp;nbsp;$value;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;string&amp;nbsp;$email&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set(string&amp;nbsp;$value)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!filter_var($value,&amp;nbsp;FILTER_VALIDATE_EMAIL))&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw&amp;nbsp;new&amp;nbsp;\ValueError(&amp;#39;邮箱格式不正确&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;email&amp;nbsp;=&amp;nbsp;strtolower($value);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;__construct(string&amp;nbsp;$name,&amp;nbsp;string&amp;nbsp;$email)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;name&amp;nbsp;=&amp;nbsp;$name;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;email&amp;nbsp;=&amp;nbsp;$email;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

$user&amp;nbsp;=&amp;nbsp;new&amp;nbsp;User(&amp;#39;Alice&amp;#39;,&amp;nbsp;&amp;#39;Alice@Example.COM&amp;#39;);
echo&amp;nbsp;$user-&amp;gt;name;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;ALICE（get&amp;nbsp;钩子转大写）
echo&amp;nbsp;$user-&amp;gt;email;&amp;nbsp;&amp;nbsp;//&amp;nbsp;输出:&amp;nbsp;alice@example.com（set&amp;nbsp;钩子转小写存储）&lt;/pre&gt;&lt;p&gt;使用属性钩子后，无需额外定义 &lt;code&gt;getName()&lt;/code&gt;、&lt;code&gt;setName()&lt;/code&gt; 等方法，代码量大幅减少，逻辑也更聚焦。&lt;/p&gt;&lt;h2&gt;新增数组函数：array_find()、array_find_key() 等&lt;/h2&gt;&lt;p&gt;PHP 8.4 新增了 4 个实用的数组函数，填补了长期以来依赖 &lt;code&gt;array_filter&lt;/code&gt; 变通实现的空白：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;array_find(array, callback)&lt;/code&gt;：返回第一个满足条件的元素值，未找到返回 &lt;code&gt;null&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;array_find_key(array, callback)&lt;/code&gt;：返回第一个满足条件的元素键名，未找到返回 &lt;code&gt;null&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;array_any(array, callback)&lt;/code&gt;：只要有一个元素满足条件就返回 &lt;code&gt;true&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;array_all(array, callback)&lt;/code&gt;：所有元素都满足条件才返回 &lt;code&gt;true&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&amp;lt;?php

$users&amp;nbsp;=&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&amp;#39;name&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;张三&amp;#39;,&amp;nbsp;&amp;#39;age&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;28,&amp;nbsp;&amp;#39;vip&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;false],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&amp;#39;name&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;李四&amp;#39;,&amp;nbsp;&amp;#39;age&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;35,&amp;nbsp;&amp;#39;vip&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;true],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&amp;#39;name&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;王五&amp;#39;,&amp;nbsp;&amp;#39;age&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;22,&amp;nbsp;&amp;#39;vip&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;true],
];

//&amp;nbsp;找到第一个&amp;nbsp;VIP&amp;nbsp;用户
$firstVip&amp;nbsp;=&amp;nbsp;array_find($users,&amp;nbsp;fn($u)&amp;nbsp;=&amp;gt;&amp;nbsp;$u[&amp;#39;vip&amp;#39;]);
//&amp;nbsp;结果:&amp;nbsp;[&amp;#39;name&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;李四&amp;#39;,&amp;nbsp;&amp;#39;age&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;35,&amp;nbsp;&amp;#39;vip&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;true]

//&amp;nbsp;找到第一个&amp;nbsp;VIP&amp;nbsp;用户的索引
$firstVipKey&amp;nbsp;=&amp;nbsp;array_find_key($users,&amp;nbsp;fn($u)&amp;nbsp;=&amp;gt;&amp;nbsp;$u[&amp;#39;vip&amp;#39;]);
//&amp;nbsp;结果:&amp;nbsp;1

//&amp;nbsp;是否存在未成年用户
$hasMinor&amp;nbsp;=&amp;nbsp;array_any($users,&amp;nbsp;fn($u)&amp;nbsp;=&amp;gt;&amp;nbsp;$u[&amp;#39;age&amp;#39;]&amp;nbsp;&amp;lt;&amp;nbsp;18);
//&amp;nbsp;结果:&amp;nbsp;false

//&amp;nbsp;是否所有用户都已成年
$allAdult&amp;nbsp;=&amp;nbsp;array_all($users,&amp;nbsp;fn($u)&amp;nbsp;=&amp;gt;&amp;nbsp;$u[&amp;#39;age&amp;#39;]&amp;nbsp;&amp;gt;=&amp;nbsp;18);
//&amp;nbsp;结果:&amp;nbsp;true

echo&amp;nbsp;$firstVip[&amp;#39;name&amp;#39;];&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;李四
echo&amp;nbsp;$firstVipKey;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;1
var_dump($hasMinor);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;bool(false)
var_dump($allAdult);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;bool(true)&lt;/pre&gt;&lt;p&gt;这些函数大大提升了数组操作的语义化程度，代码意图更清晰，也更易于维护。&lt;/p&gt;&lt;h2&gt;new 表达式无需括号即可链式调用&lt;/h2&gt;&lt;p&gt;PHP 8.4 之前，在 &lt;code&gt;new&lt;/code&gt; 表达式之后直接调用方法需要加括号，否则会报解析错误。PHP 8.4 移除了这一限制：&lt;/p&gt;&lt;pre&gt;&amp;lt;?php

class&amp;nbsp;QueryBuilder&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;array&amp;nbsp;$conditions&amp;nbsp;=&amp;nbsp;[];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;?int&amp;nbsp;$limit&amp;nbsp;=&amp;nbsp;null;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;where(string&amp;nbsp;$condition):&amp;nbsp;static&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;conditions[]&amp;nbsp;=&amp;nbsp;$condition;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$this;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;limit(int&amp;nbsp;$n):&amp;nbsp;static&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;limit&amp;nbsp;=&amp;nbsp;$n;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$this;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;build():&amp;nbsp;string&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;=&amp;nbsp;&amp;#39;SELECT&amp;nbsp;*&amp;nbsp;FROM&amp;nbsp;users&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;($this-&amp;gt;conditions)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;.=&amp;nbsp;&amp;#39;&amp;nbsp;WHERE&amp;nbsp;&amp;#39;&amp;nbsp;.&amp;nbsp;implode(&amp;#39;&amp;nbsp;AND&amp;nbsp;&amp;#39;,&amp;nbsp;$this-&amp;gt;conditions);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;($this-&amp;gt;limit&amp;nbsp;!==&amp;nbsp;null)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;.=&amp;nbsp;&amp;#39;&amp;nbsp;LIMIT&amp;nbsp;&amp;#39;&amp;nbsp;.&amp;nbsp;$this-&amp;gt;limit;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$sql;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

//&amp;nbsp;PHP&amp;nbsp;8.4：无需括号，直接链式调用
$sql&amp;nbsp;=&amp;nbsp;new&amp;nbsp;QueryBuilder()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;gt;where(&amp;#39;age&amp;nbsp;&amp;gt;&amp;nbsp;18&amp;#39;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;gt;where(&amp;#39;status&amp;nbsp;=&amp;nbsp;1&amp;#39;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;gt;limit(10)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;gt;build();

echo&amp;nbsp;$sql;
//&amp;nbsp;输出:&amp;nbsp;SELECT&amp;nbsp;*&amp;nbsp;FROM&amp;nbsp;users&amp;nbsp;WHERE&amp;nbsp;age&amp;nbsp;&amp;gt;&amp;nbsp;18&amp;nbsp;AND&amp;nbsp;status&amp;nbsp;=&amp;nbsp;1&amp;nbsp;LIMIT&amp;nbsp;10&lt;/pre&gt;&lt;p&gt;这个改进看似细小，但在大量使用 Builder 模式的项目中，可以让代码写法更加自然流畅。&lt;/p&gt;&lt;h2&gt;升级建议与注意事项&lt;/h2&gt;&lt;p&gt;在将项目迁移到 PHP 8.4 之前，有几点需要注意：&lt;/p&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;废弃特性清理&lt;/strong&gt;：PHP 8.4 废弃了部分隐式可空类型声明（如 &lt;code&gt;function foo(string $x = null)&lt;/code&gt;），需改为显式 &lt;code&gt;?string&lt;/code&gt;，建议先用 PHP_CodeSniffer 或 Rector 扫描代码库&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;属性钩子与接口&lt;/strong&gt;：接口中也可以声明带钩子要求的属性，实现类必须提供对应的钩子实现，注意检查已有接口&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;性能提升&lt;/strong&gt;：PHP 8.4 对 JIT 编译器做了优化，计算密集型场景性能有一定提升，建议在测试环境做好 benchmark 对比&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Composer 依赖&lt;/strong&gt;：检查所有依赖库是否支持 PHP 8.4，可通过 &lt;code&gt;composer outdated&lt;/code&gt; 排查不兼容包&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;总体而言，PHP 8.4 是一个质量很高的版本，属性钩子和新数组函数都是开发者期待已久的特性。建议在新项目中直接使用 PHP 8.4，老项目也可以计划在下一个维护窗口完成升级。&lt;/p&gt;</description><pubDate>Fri, 19 Jun 2026 08:08:58 +0800</pubDate></item><item><title>Jetpack Compose 状态管理全解析：从 remember 到 ViewModel 实战</title><link>https://blog.resmic.cn/post/298.html</link><description></description><pubDate>Thu, 18 Jun 2026 08:05:26 +0800</pubDate></item></channel></rss>