{"id":1299,"date":"2026-09-14T14:07:42","date_gmt":"2026-09-14T14:07:42","guid":{"rendered":"https:\/\/boochlin.com\/?p=1299"},"modified":"2026-09-14T15:28:01","modified_gmt":"2026-09-14T15:28:01","slug":"funny-vote-app-vibe-coding%e3%80%81ai-%e7%b5%90%e5%b0%8d%e8%88%87-firebase-%e9%9b%b2%e5%8e%9f%e7%94%9f%e7%b5%82%e5%b1%80%e9%9b%9c%e8%a8%98","status":"publish","type":"post","link":"https:\/\/boochlin.com\/?p=1299","title":{"rendered":"Funny vote APP \u2013 \u5f37\u8feb\u75c7\u7684 100% \u756b\u9762\u5fa9\u523b\uff1a\u628a\u5341\u5e74\u524d\u7684\u9752\u6625\u642c\u9032 Material 3\uff08\u4e94\uff09"},"content":{"rendered":"<p>\u5728\u4e0a\u4e00\u7bc7\u88e1\uff0c\u6211\u5011\u628a MVI \u55ae\u5411\u8cc7\u6599\u6d41\u6253\u9020\u5b8c\u7562\uff0c\u6d88\u6ec5\u4e86\u6240\u6709\u72c0\u614b\u6253\u67b6\u8207\u767d\u5c4f\u554f\u984c\u3002\u90a3\u6642\u5019\u6211\u5011\u53ea\u6311\u4e86\u4e00\u689d\u6700\u95dc\u9375\u7684\u6295\u7968\u4e3b\u8def\u5f91\u4f86\u9a57\u8b49\u67b6\u69cb\uff0c\u628a\u6838\u5fc3\u6d41\u7a0b\u8dd1\u5f97\u6975\u5ea6\u7d72\u6ed1\u3002<\/p>\n<p>\u6309\u7406\u8aaa\uff0c\u8eab\u70ba\u4e00\u500b\u300c\u6020\u60f0\u300d\u7684\u5de5\u7a0b\u5e2b\uff0c\u65e2\u7136\u67b6\u69cb\u6253\u901a\u4e86\u3001\u6280\u8853\u96e3\u9ede\u89e3\u6c7a\u4e86\uff0c\u9019\u6642\u5019\u5c31\u53ef\u4ee5\u62cd\u62cd\u5c41\u80a1\u6536\u5de5\u4e86\u3002\u4f46\u6bcf\u7576\u6211\u5728\u624b\u6a5f\u4e0a\u6253\u958b\u90a3\u500b\u53ea\u5269\u4e0b\u56db\u500b\u7c21\u6f54\u756b\u9762\u7684\u65b0\u7248 App\uff0c\u770b\u8457\u5149\u79bf\u79bf\u7684\u9078\u55ae\uff0c\u5fc3\u88e1\u7e3d\u6709\u4e00\u7a2e\u8aaa\u4e0d\u51fa\u7684\u5931\u843d\u611f\u3002<\/p>\n<p>\u5341\u5e74\u524d\u5728 2016 \u5e74\u7684 <code>master<\/code> \u5206\u652f\u88e1\uff0c\u90a3\u500b\u6211\u6bcf\u5929\u81ea\u5df1\u4e0b\u8f09\u4f86\u73a9\u7684 FunnyVote\uff0c\u88e1\u9762\u53ef\u4e0d\u53ea\u6709\u51b7\u51b0\u51b0\u7684\u6295\u7968\u5217\u8868\u3002\u90a3\u88e1\u5c01\u5b58\u4e86\u6eff\u6eff\u7684\u5fc3\u8840\uff1a\u516d\u9801\u5716\u6587\u4e26\u8302\u7684\u555f\u52d5\u5c0e\u89bd\u6559\u5b78\uff08<code>TutorialActivity<\/code>\uff09\u3001\u56db\u500b\u4ecb\u7d39\u958b\u767c\u5718\u968a\u8207\u689d\u6b3e\u7684\u95dc\u65bc\u5b50\u9801\u9762\uff08<code>AboutActivity<\/code>\uff09\u3001\u81ea\u8a02\u624b\u52e2\u7684\u5e95\u5c64\u5206\u4eab\u5f48\u7a97\uff08<code>ShareBottomSheet<\/code>\uff09\uff0c\u751a\u81f3\u9084\u6709\u7576\u521d\u70ba\u4e86\u8cfa\u5e7e\u584a\u7f8e\u91d1\u4e32\u63a5\u7684 AdMob \u5ee3\u544a\u6a6b\u5e45\u3002<\/p>\n<p>\u696d\u754c\u5f88\u591a\u958b\u6e90\u5c08\u6848\u91cd\u69cb\uff0c\u5f80\u5f80\u53ea\u523b\u4e86\u6700\u7c21\u55ae\u7684\u5169\u4e09\u500b\u756b\u9762\uff0c\u9047\u5230\u96e3\u641e\u7684\u5f15\u5c0e\u9801\u3001\u81ea\u8a02\u5f48\u7a97\u6216\u908a\u7de3\u689d\u6b3e\uff0c\u5c31\u76f4\u63a5\u7576\u4f5c\u6c92\u9019\u56de\u4e8b\u3002\u9019\u7a2e\u53ea\u505a\u6838\u5fc3\u7684\u300c\u6a23\u54c1\u5c4b\u67b6\u69cb\u300d\uff0c\u9a19\u5f97\u4e86\u9762\u8a66\u5b98\uff0c\u9a19\u4e0d\u904e\u81ea\u5df1\u7684\u5fc3\u3002<\/p>\n<p>\u9019\u4e0d\u662f\u7406\u6027\u7684\u6280\u8853\u6c7a\u7b56\uff0c\u9019\u662f\u4e00\u500b\u539f\u5275\u8005\u7684\u60c5\u611f\u6f54\u7656\u3002\u65bc\u662f\uff0c\u5728 2026 \u5e74\u7684 <code>modern-android<\/code> \u5206\u652f\u4e0a\uff0c\u6211\u6c7a\u5b9a\u5c55\u958b\u4e00\u5834\u786c\u6838\u7684\u9ad4\u529b\u6d3b\uff1a<strong>\u628a\u5341\u5e74\u524d\u7684\u9752\u6625\u8207\u7d30\u7bc0\uff0c\u4e00\u500b\u4e0d\u6f0f\u5730 100% \u642c\u9032\u73fe\u4ee3 Material 3\uff01<\/strong><\/p>\n<hr \/>\n<h2>\u4e00\u3001 \u9ad4\u529b\u6d3b\u4e00\uff1a\u5f9e 48&#215;48 \u50cf\u7d20\u6ce5\u6f6d\u5230\u73fe\u4ee3 SVG \u5411\u91cf\u5716\u6a19<\/h2>\n<p>\u7576\u6211\u6253\u958b 2016 \u5e74\u7684 <code>res\/drawable-mdpi<\/code> \u8207 <code>drawable-hdpi<\/code> \u76ee\u9304\u6642\uff0c\u773c\u524d\u7684\u666f\u8c61\u7c21\u76f4\u662f\u4e00\u5834\u8996\u89ba\u707d\u96e3\u3002<\/p>\n<p>\u5404\u4f4d\u8cc7\u6df1\u7684 Android \u958b\u767c\u8005\u61c9\u8a72\u9084\u8a18\u5f97\uff0c\u5341\u5e74\u524d\u70ba\u4e86\u9069\u61c9\u4e0d\u540c\u87a2\u5e55\u5bc6\u5ea6\uff0c\u8a2d\u8a08\u5e2b\u5f97\u8f9b\u8f9b\u82e6\u82e6\u628a\u4e00\u5f35\u5716\u5207\u6210 mdpi\u3001hdpi\u3001xhdpi\u3001xxhdpi\u3001xxxhdpi \u4e94\u5957\u4e0d\u540c\u5927\u5c0f\u7684\u9ede\u9663 PNG\u3002\u800c\u5728\u7576\u5e74\u7684 FunnyVote \u88e1\uff0c\u5f88\u591a\u5716\u6a19\u751a\u81f3\u53ea\u6709 mdpi\uff0848&#215;48 \u50cf\u7d20\uff09\u7684\u8d85\u4f4e\u89e3\u6790\u5ea6\u5c0f\u5716\u3002<\/p>\n<p>\u5728\u5341\u5e74\u524d Nexus 4 \u6216 Galaxy S3 \u90a3\u7a2e\u87a2\u5e55\u4e0a\uff0c\u9019\u4e9b\u5c0f\u5716\u770b\u8d77\u4f86\u9084\u7b97\u904e\u5f97\u53bb\u3002\u4f46\u5728 2026 \u5e74\u7684\u9ad8\u89e3\u6790\u5ea6\u65d7\u8266\u6a5f\uff08\u52d5\u8f12 400+ ppi\uff09\u4e0a\u628a\u9019\u4e9b\u8001\u820a PNG \u6e32\u67d3\u51fa\u4f86\u6642\uff0c<strong>\u5716\u6a19\u7cca\u5f97\u50cf\u6253\u4e86\u91cd\u5ea6\u99ac\u8cfd\u514b\uff0c\u92f8\u9f52\u908a\u7de3\u92b3\u5229\u5230\u53ef\u4ee5\u5272\u50b7\u773c\u775b<\/strong>\uff01<\/p>\n<p>\u5728\u73fe\u4ee3 Compose \u958b\u767c\u4e2d\uff0c\u9ede\u9663 PNG \u65e9\u5c31\u88ab\u6642\u4ee3\u6dd8\u6c70\u4e86\u3002\u6a19\u6e96\u505a\u6cd5\u662f\u5168\u9762\u4f7f\u7528\u5411\u91cf\u5716\u5f62\uff08Vector Drawable \/ SVG\uff09\uff0c\u7531 GPU \u5728\u6e32\u67d3\u6642\u5373\u6642\u8a08\u7b97\u8c9d\u8332\u66f2\u7dda\uff0c\u4e0d\u8ad6\u653e\u5927\u5230\u5e7e\u540b\u87a2\u5e55\u90fd\u92b3\u5229\u7121\u6bd4\u3002<\/p>\n<p>\u90a3\u5e7e\u5929\uff0c\u6211\u8010\u8457\u6027\u5b50\u628a\u820a\u5c08\u6848\u88e1\u5e7e\u5341\u500b\u9673\u820a\u7684 PNG \u6316\u4e86\u51fa\u4f86\u3002\u6709\u4e9b\u5716\u6a19\u5728\u958b\u6e90\u5716\u5eab\u88e1\u627e\u5f97\u5230\u5c0d\u61c9\u7684\u6a19\u6e96 Material Icon\uff0c\u6211\u5c31\u76f4\u63a5\u66ff\u63db\u6210 Compose \u5b98\u65b9\u7684 <code>ImageVector<\/code>\uff1a<\/p>\n<pre><code class=\"language-kotlin\">\/\/ \u7528\u73fe\u4ee3 AutoMirrored \u8207\u5b98\u65b9\u5411\u91cf\u5716\u6a19\u66ff\u63db\u9673\u820a\u8cc7\u6e90\nIcon(\n    imageVector = Icons.AutoMirrored.Filled.ArrowBack,\n    contentDescription = \"\u8fd4\u56de\u4e0a\u4e00\u9801\",\n    tint = MaterialTheme.colorScheme.onSurface\n)<\/code><\/pre>\n<p>\u800c\u5c0d\u65bc\u90a3\u4e9b FunnyVote \u7368\u5275\u7684\u81ea\u8a02\u5716\u5f62\uff08\u4f8b\u5982\u6295\u7968\u5c0f\u624b\u3001\u7279\u8272\u5fbd\u7ae0\uff09\uff0c\u6211\u7528\u5411\u91cf\u8edf\u9ad4\u4e00\u500b\u9ede\u4e00\u500b\u9328\u9ede\u91cd\u65b0\u52fe\u52d2\uff0c\u532f\u51fa\u6210\u4e7e\u6de8\u7684 SVG\uff0c\u518d\u900f\u904e Android Studio \u7684 Vector Asset Studio \u8f49\u6210 <code>VectorDrawable<\/code> XML\u3002\u5149\u662f\u9019\u9805\u6e05\u7406\u8cc7\u7522\u7684\u82e6\u5de5\uff0c\u5c31\u82b1\u4e86\u6211\u6574\u6574\u5169\u500b\u6df1\u591c\u3002\u4f46\u7576\u770b\u5230\u6240\u6709\u5716\u6a19\u5728\u624b\u6a5f\u4e0a\u6676\u7469\u5254\u900f\u5730\u6d6e\u73fe\u6642\uff0c\u90a3\u7a2e\u8996\u89ba\u8212\u9069\u611f\u771f\u7684\u7121\u53ef\u53d6\u4ee3\u3002<\/p>\n<hr \/>\n<h2>\u4e8c\u3001 \u9ad4\u529b\u6d3b\u4e8c\uff1a30+ \u4efd XML \u5beb\u6b7b\u984f\u8272\u7684\u9664\u9b45\u5de5\u7a0b\uff0c\u9077\u5f99\u81f3 Material 3<\/h2>\n<p>\u641e\u5b9a\u5716\u6a19\u5f8c\uff0c\u63a5\u4e0b\u4f86\u8981\u9762\u5c0d\u7684\u662f\u8272\u5f69\u7cfb\u7d71\u7684\u5d29\u6f70\u3002<\/p>\n<p>\u5728\u5341\u5e74\u524d\u7684 <code>styles.xml<\/code> \u8207\u5404\u500b\u6392\u7248 XML \u88e1\uff0c\u5145\u65a5\u8457\u6eff\u6eff\u7684\u786c\u7de8\u78bc\u984f\u8272\uff08Hardcoded Colors\uff09\uff1a<\/p>\n<pre><code class=\"language-xml\">&lt;!-- 2016 \u5e74\u7684\u7d93\u5178 Material 1 \u5beb\u6b7b\u914d\u8272 --&gt;\n&lt;color name=\"colorPrimary\"&gt;#3F51B5&lt;\/color&gt; &lt;!-- \u7d93\u5178\u975b\u85cd\u8272 --&gt;\n&lt;color name=\"colorPrimaryDark\"&gt;#303F9F&lt;\/color&gt;\n&lt;color name=\"colorAccent\"&gt;#FF4081&lt;\/color&gt; &lt;!-- \u4eae\u7c89\u7d05\u5f37\u8abf\u8272 --&gt;\n&lt;color name=\"textColorPrimary\"&gt;#212121&lt;\/color&gt;\n&lt;color name=\"background_gray\"&gt;#F5F5F5&lt;\/color&gt;<\/code><\/pre>\n<p>\u90a3\u6642\u5019\u7684\u5beb\u6cd5\u6975\u5176\u91ce\u883b\u3002\u53ea\u8981\u60f3\u6539\u500b\u80cc\u666f\u8272\uff0c\u5927\u5bb6\u5c31\u5728 XML \u88e1\u96a8\u624b\u5beb\u500b <code>android:background=\"#F5F5F5\"<\/code>\u3002\u7d50\u679c\u6574\u500b\u5c08\u6848\u88e1\u6563\u843d\u8457\u5e7e\u5341\u7a2e\u6df1\u6dfa\u4e0d\u4e00\u7684\u7070\u8272\u8207\u85cd\u8272\uff0c\u5b8c\u5168\u6c92\u6709\u4efb\u4f55\u8a2d\u8a08\u898f\u7bc4\u53ef\u8a00\u3002\u800c\u4e14\u66f4\u81f4\u547d\u7684\u662f\uff1a<strong>\u7576\u5e74\u7684\u5c08\u6848\u6839\u672c\u4e0d\u652f\u63f4\u6df1\u8272\u6a21\u5f0f\uff08Dark Mode\uff09<\/strong>\uff01\u53ea\u8981\u4f7f\u7528\u8005\u5728\u7cfb\u7d71\u5207\u63db\u5230\u591c\u9593\u6a21\u5f0f\uff0cApp \u756b\u9762\u4f9d\u7136\u662f\u4e00\u7247\u523a\u773c\u7684\u4eae\u767d\u8272\u3002<\/p>\n<p>\u5728 <code>modern-android<\/code> \u5206\u652f\u4e2d\uff0c\u6211\u5011\u4e00\u53e3\u6c23\u5347\u7d1a\u5230\u4e86 Material 3\uff08M3\uff09\u8a2d\u8a08\u8a9e\u8a00\uff0c\u5efa\u7acb\u4e86\u6a19\u6e96\u7684\u8a9e\u7fa9\u5316\u8272\u76e4\u7cfb\u7d71\uff1a<\/p>\n<pre><code class=\"language-kotlin\">\/\/ 2026 \u5e74\u7684 Material 3 \u8a9e\u7fa9\u5316\u8272\u5f69\u4e3b\u984c\nprivate val LightColorScheme = lightColorScheme(\n    primary = Color(0xFF1E88E5),\n    onPrimary = Color.White,\n    primaryContainer = Color(0xFFD1E4FF),\n    onPrimaryContainer = Color(0xFF001D36),\n    secondary = Color(0xFF535F70),\n    background = Color(0xFFFDFCFF),\n    surface = Color(0xFFFDFCFF),\n    onSurface = Color(0xFF1A1C1E)\n)\n\nprivate val DarkColorScheme = darkColorScheme(\n    primary = Color(0xFF9ECAFF),\n    onPrimary = Color(0xFF003258),\n    primaryContainer = Color(0xFF00497D),\n    onPrimaryContainer = Color(0xFFD1E4FF),\n    background = Color(0xFF1A1C1E),\n    surface = Color(0xFF1A1C1E),\n    onSurface = Color(0xFFE2E2E6)\n)<\/code><\/pre>\n<p>\u5728 Compose \u88e1\u9762\uff0c\u6240\u6709\u6587\u5b57\u3001\u6309\u9215\u8207\u5361\u7247\u7684\u984f\u8272\uff0c\u4e00\u5f8b\u5f37\u5236\u5f15\u7528 <code>MaterialTheme.colorScheme.*<\/code>\uff1a<\/p>\n<pre><code class=\"language-kotlin\">\/\/ \u4e7e\u6de8\u5229\u843d\u7684\u8a9e\u7fa9\u5316\u5143\u4ef6\u5ba3\u544a\nText(\n    text = vote.title,\n    style = MaterialTheme.typography.titleMedium,\n    color = MaterialTheme.colorScheme.onSurface \/\/ \u81ea\u52d5\u6839\u64da\u65e5\u591c\u9593\u6a21\u5f0f\u5207\u63db\u9069\u7576\u8272\u5f69\n)<\/code><\/pre>\n<p>\u9019\u9805\u6539\u9020\u6700\u795e\u5947\u7684\u5730\u65b9\u5728\u65bc\uff1a<strong>\u6df1\u8272\u6a21\u5f0f\u7684\u652f\u63f4\u76f4\u63a5\u8b8a\u6210\u4e86\u514d\u8cbb\u8d08\u54c1<\/strong>\u3002\u7576\u624b\u6a5f\u5207\u63db\u5230\u591c\u9593\u6a21\u5f0f\u6642\uff0c\u7cfb\u7d71\u81ea\u52d5\u5c07\u80cc\u666f\u7f6e\u63db\u70ba\u512a\u96c5\u7684\u6697\u9ed1\u8272\u8abf\uff0c\u6587\u5b57\u81ea\u52d5\u53cd\u767d\uff0c\u5c0d\u6bd4\u5ea6\u5b8c\u7f8e\u7b26\u5408 WCAG \u7121\u969c\u7919\u6a19\u6e96\uff0c\u518d\u4e5f\u4e0d\u6703\u5728\u6df1\u591c\u4eae\u778e\u4f7f\u7528\u8005\u7684\u96d9\u773c\u3002<\/p>\n<hr \/>\n<h2>\u4e09\u3001 \u9ad4\u529b\u6d3b\u4e09\uff1a100% \u5fa9\u523b 6 \u9801\u65b0\u624b\u5f15\u5c0e\u8207\u81ea\u8a02\u5206\u4eab\u5f48\u7a97<\/h2>\n<p>\u57fa\u790e\u8a2d\u65bd\u4fee\u6574\u5b8c\u7562\u5f8c\uff0c\u6211\u958b\u59cb\u4e00\u9801\u4e00\u9801\u5730\u7121\u640d\u5fa9\u523b\u820a\u756b\u9762\u3002<\/p>\n<p>\u6700\u5148\u52d5\u5de5\u7684\u662f\u7576\u5e74\u7684 6 \u9801\u555f\u52d5\u6559\u5b78\uff08<code>TutorialActivity<\/code>\uff09\u3002\u5341\u5e74\u524d\u6211\u5011\u662f\u7528 <code>ViewPager<\/code> \u642d\u914d 6 \u4efd\u7368\u7acb\u7684 XML \u4f86\u8f2a\u64ad\u5716\u7247\u8207\u6587\u5b57\u8aaa\u660e\u3002\u5728\u73fe\u4ee3 Compose \u88e1\u9762\uff0c\u6211\u5011\u7528 <code>HorizontalPager<\/code> \u91cd\u65b0\u5fa9\u523b\u4e86\u9019\u6bb5\u7d93\u5178\u56de\u61b6\uff1a<\/p>\n<pre><code class=\"language-kotlin\">\/\/ \u73fe\u4ee3\u7248 6 \u9801\u6559\u5b78\u8f2a\u64ad\u5c0e\u89bd\n@Composable\nfun TutorialScreen(onFinishTutorial: () -&gt; Unit) {\n    val pagerState = rememberPagerState(pageCount = { 6 })\n    val coroutineScope = rememberCoroutineScope()\n\n    Column(modifier = Modifier.fillMaxSize()) {\n        HorizontalPager(\n            state = pagerState,\n            modifier = Modifier.weight(1f)\n        ) { page -&gt;\n            TutorialPageContent(pageIndex = page)\n        }\n        \n        \/\/ \u5e95\u90e8\u5713\u9ede\u6307\u793a\u5668\u8207\u8df3\u904e\u6309\u9215\n        TutorialBottomBar(\n            pagerState = pagerState,\n            onSkipClick = onFinishTutorial,\n            onNextClick = {\n                if (pagerState.currentPage &lt; 5) {\n                    coroutineScope.launch { pagerState.animateScrollToPage(pagerState.currentPage + 1) }\n                } else {\n                    onFinishTutorial()\n                }\n            }\n        )\n    }\n}<\/code><\/pre>\n<p>\u63a5\u8457\u662f\u5341\u5e74\u524d\u90a3\u500b\u5ba2\u88fd\u5316\u7684\u81ea\u8a02\u5206\u4eab\u9078\u55ae\uff08<code>ShareBottomSheet<\/code>\uff09\u3002\u90a3\u6642\u5019\u70ba\u4e86\u89e3\u6c7a\u300c\u5206\u4eab\u5230 Facebook\u3001Twitter\u3001LINE\u3001\u8907\u88fd\u9023\u7d50\u300d\u7684\u6309\u9215\u6392\u7248\uff0c\u6211\u5011\u5beb\u4e86\u4e00\u500b\u5c08\u5c6c\u7684 DialogFragment\uff0c\u5149\u662f\u8655\u7406\u5e95\u90e8\u5f48\u51fa\u52d5\u756b\u5c31\u8e29\u4e86\u4e0d\u5c11\u5751\u3002\u73fe\u5728\u7528 Compose \u7684 <code>ModalBottomSheet<\/code>\uff0c\u914d\u5408 <code>rememberModalBottomSheetState<\/code>\uff0c\u5e7e\u5341\u884c\u4ee3\u78bc\u5c31\u80fd\u505a\u51fa\u64c1\u6709\u7d72\u6ed1\u963b\u5c3c\u611f\u8207\u908a\u7de3\u624b\u52e2\u62d6\u66f3\u7684\u73fe\u4ee3\u5e95\u90e8\u62bd\u5c5c\u3002<\/p>\n<p>\u6211\u5011\u9023\u56db\u500b\u300c\u95dc\u65bc\u300d\u5b50\u9801\u9762\uff08\u7248\u672c\u8cc7\u8a0a\u3001\u8d0a\u52a9\u540d\u55ae\u3001\u96b1\u79c1\u689d\u6b3e\u3001\u5e38\u898b Q&amp;A\uff09\u8207\u539f\u672c\u7684\u81ea\u7814\u4fc3\u92b7\u6a6b\u5e45\uff08Promotion Banner\uff09\u90fd\u901a\u901a\u642c\u4e86\u56de\u4f86\u3002\u770b\u8457\u9019\u500b\u4ecb\u9762\uff0c\u5341\u5e74\u524d\u6bcf\u5929\u5728\u5496\u5561\u5ef3 Debug \u7684\u8a18\u61b6\uff0c\u5f77\u5f7f\u7a7f\u8d8a\u6642\u7a7a\u91cd\u65b0\u9bae\u6d3b\u4e86\u8d77\u4f86\u3002<\/p>\n<hr \/>\n<h2>\u56db\u3001 \u5be6\u6a5f\u9a57\u6536\uff1a\u5728 Samsung S23 \u4e0a\u6ed1\u6eff 120Hz \u7684\u6975\u81f4\u723d\u611f<\/h2>\n<p>\u7576\u5168\u90e8 20 \u5e7e\u500b\u756b\u9762\u8207\u5f48\u7a97\u5fa9\u523b\u5b8c\u7562\u5f8c\uff0c\u5230\u4e86\u6700\u6fc0\u52d5\u4eba\u5fc3\u7684\u9a57\u6536\u6642\u523b\u3002<\/p>\n<p>\u6211\u62ff\u51fa\u5be6\u9ad4\u6e2c\u8a66\u6a5f Samsung Galaxy S23\uff0c\u900f\u904e ADB \u628a Release \u7248\u672c\u5b89\u88dd\u9032\u624b\u6a5f\u3002\u63a5\u8457\uff0c\u5728\u958b\u767c\u8005\u9078\u9805\u4e2d\u958b\u555f\u7d93\u5178\u7684<strong>\u300cGPU \u5448\u73fe\u6a21\u5f0f\u5206\u6790\uff08Profile HWUI Rendering\uff09\u300d<\/strong>\uff0c\u9078\u64c7\u5728\u87a2\u5e55\u4e0a\u4ee5\u9577\u689d\u5716\u986f\u793a\u3002<\/p>\n<p>\u5728 Android \u87a2\u5e55\u4e0a\uff0c\u6709\u4e00\u689d\u9192\u76ee\u7684\u7da0\u8272\u6c34\u5e73\u57fa\u6e96\u7dda\uff0c\u4ee3\u8868\u6bcf\u5e40\u6e32\u67d3\u8017\u6642\u7684\u53ca\u683c\u9580\u6abb\uff08120Hz \u87a2\u5e55\u5c0d\u61c9\u7684\u662f 8.3 \u6beb\u79d2\uff09\u3002<\/p>\n<p>\u6211\u6309\u4f4f\u87a2\u5e55\uff0c\u5c0d\u8457\u71b1\u9580\u6295\u7968\u5217\u8868\u3001\u641c\u5c0b\u5206\u9801\u3001\u5f15\u5c0e\u8f2a\u64ad\u72c2\u7529\u624b\u6307\uff0c\u7528\u6700\u5feb\u7684\u901f\u5ea6\u4e0a\u4e0b\u6ed1\u52d5\uff1a<\/p>\n<p><strong>\u756b\u9762\u4e0a\u6bcf\u4e00\u500b\u67f1\u72c0\u5716\uff0c\u7a69\u5982\u78d0\u77f3\u5730\u8cbc\u5728\u6700\u5e95\u90e8\uff0c\u5168\u90e8\u7dca\u8cbc\u8457\u7da0\u8272\u57fa\u6e96\u7dda\u4e4b\u4e0b\uff01\u6bcf\u4e00\u5e40\u7684\u7e6a\u88fd\u6642\u9593\u88ab\u58d3\u5236\u5728 3 \u5230 5 \u6beb\u79d2\u4e4b\u9593\uff0c\u6c92\u6709\u4efb\u4f55\u4e00\u6839\u9577\u689d\u885d\u7834\u57fa\u6e96\u7dda\uff01<\/strong><\/p>\n<p>\u770b\u8457 120fps \u4e00\u689d\u7da0\u7dda\u6ed1\u5230\u5e95\u7684\u6975\u81f4\u6d41\u66a2\u611f\uff0c\u6211\u4e0d\u7981\u56de\u60f3\u8d77\u5341\u5e74\u524d Android 5.0 \/ 6.0 \u6642\u4ee3\u3002\u90a3\u6642\u5019\u5373\u4f7f\u5728\u9802\u7d1a\u624b\u6a5f\u4e0a\u6ed1 ListView\uff0c\u7a0d\u5fae\u9047\u5230\u5716\u7247\u8f09\u5165\u6216\u8907\u96dc\u6392\u7248\uff0c\u9577\u689d\u5716\u5c31\u52d5\u4e0d\u52d5\u7d05\u85cd\u76f8\u9593\u3001\u9ad8\u8073\u5165\u96f2\uff0c\u4f34\u96a8\u8457\u8089\u773c\u53ef\u898b\u7684\u9813\u632b\u611f\u3002\u5341\u5e74\u904e\u53bb\u4e86\uff0c\u786c\u9ad4\u7684\u6f14\u9032\u8207 Compose \u7684\u6210\u719f\uff0c\u7d42\u65bc\u8b93 Android \u7684\u6e32\u67d3\u9ad4\u9a57\u9054\u5230\u4e86\u85dd\u8853\u7d1a\u7684\u5883\u754c\u3002<\/p>\n<hr \/>\n<h2>\u4e94\u3001 \u7d42\u6975\u5c37\u5c2c\uff1a\u8dd1\u8eca\u523b\u597d\u4e86\uff0c\u5f8c\u7aef\u4f3a\u670d\u5668\u65e9\u5c31\u5165\u571f\u516b\u5e74\u4e86<\/h2>\n<p>\u6b63\u7576\u6211\u6c89\u6d78\u5728\u300c\u756b\u9762\u5fa9\u523b\u5b8c\u7562\u3001\u6548\u80fd\u5b8c\u7f8e\u767b\u9802\u300d\u7684\u5de8\u5927\u6210\u5c31\u611f\u4e2d\uff0c\u6211\u9ede\u958b\u4e86 App \u4e2d\u7684\u300c\u5237\u65b0\u8cc7\u6599\u300d\u6309\u9215\u3002<\/p>\n<p>\u8f49\u5708\u5708\u8f49\u4e86\u5341\u79d2\u9418\uff0c\u756b\u9762\u5f48\u51fa\u4e86\u4e00\u500b\u719f\u6089\u7684\u932f\u8aa4\u8a0a\u606f\uff1a<code>java.net.UnknownHostException: Unable to resolve host \"funny-vote.com\"<\/code>\u3002<\/p>\n<p>\u6211\u7576\u5834\u6123\u5728\u5de5\u4f4d\u4e0a\u3002<\/p>\n<p>\u6211\u7acb\u523b\u7ffb\u51fa\u7576\u5e74\u7684 <code>api.properties<\/code> \u8207 Git \u6b77\u53f2\u7d00\u9304\u3002\u539f\u4f86\u5728 2016 \u5e74\uff0c\u6211\u5011\u5c08\u6848\u7684\u5f8c\u7aef\u662f\u597d\u670b\u53cb JJJ \u7528 PHP \u5beb\u7684\uff0c\u67b6\u5728 DigitalOcean \u6bcf\u500b\u6708\u4e94\u7f8e\u5143\u7684\u865b\u64ec\u4e3b\u6a5f\uff08VPS\uff09\u4e0a\uff1b\u7db2\u5740 <code>funny-vote.com<\/code> \u7576\u5e74\u5728 Godaddy \u8cb7\u7684\u4e00\u5e74\u8981 699 \u53f0\u5e63\u3002<\/p>\n<p>\u7136\u800c\uff0c\u9019\u5341\u5e74\u4f86\u8ab0\u4e5f\u6c92\u53bb\u7ba1\u5b83\u3002\u57df\u540d\u65e9\u5c31\u904e\u671f\u88ab\u4e0d\u77e5\u540d\u7684\u7db2\u5740\u87d1\u8782\u8cb7\u8d70\u4e86\uff0c\u90a3\u53f0\u4e94\u7f8e\u5143\u7684\u4e3b\u6a5f\uff0c\u4e5f\u65e9\u5728\u516b\u5e74\u524d\u5c31\u56e0\u70ba\u6b20\u8cbb\u88ab\u4e3b\u6a5f\u5546\u6574\u6a5f\u522a\u9664\u3001\u7070\u98db\u7159\u6ec5\u4e86\uff01<\/p>\n<p>\u9019\u7c21\u76f4\u662f\u5929\u5927\u7684\u5e7d\u9ed8\uff1a<strong>\u6211\u5011\u82b1\u4e86\u597d\u5e7e\u500b\u6708\uff0c\u628a\u5ba2\u6236\u7aef\u5f9e 2016 \u5e74\u7684\u99ac\u8eca\u9032\u5316\u6210\u4e86 2026 \u5e74\u7684\u9802\u7d1a\u8d85\u8dd1\uff1b\u7d50\u679c\u5f15\u64ce\u84cb\u4e00\u6380\u958b\uff0c\u88e1\u9762\u7684\u767c\u52d5\u6a5f\u65e9\u5c31\u5316\u6210\u4e86\u7070\u71fc\uff01<\/strong>\u6211\u5011\u7adf\u7136\u662f\u5728\u62ff\u8457 Mock \u975c\u614b\u8cc7\u6599\uff0c\u81ea\u55e8\u4e86\u6574\u6574\u4e00\u500b\u79ae\u62dc\uff01<\/p>\n<p>\u8eab\u70ba\u4e00\u500b\u6709\u5c0a\u56b4\u7684\u5de5\u7a0b\u5e2b\uff0c\u6211\u7d55\u4e0d\u5141\u8a31\u81ea\u5df1\u7684\u4f5c\u54c1\u53ea\u662f\u4e00\u500b\u53ea\u80fd\u770b Demo \u7684\u5047 App\u3002\u4f46\u5341\u5e74\u524d\u7684 PHP \u4ee3\u78bc\u65e9\u5c31\u907a\u5931\u5728\u6642\u5149\u6a5f\u88e1\uff0c\u73fe\u5728\u7684\u6211\uff0c\u4e5f\u7d55\u4e0d\u60f3\u518d\u82b1\u6642\u9593\u53bb\u6298\u9a30 Linux \u6307\u4ee4\u3001Nginx \u8a2d\u5b9a\u6a94\u8207 MySQL \u9023\u7dda\u6c60\u3002<\/p>\n<p>\u5982\u4f55\u5728\u4e00\u884c\u4f3a\u670d\u5668\u4ee3\u78bc\u90fd\u4e0d\u60f3\u7dad\u8b77\u7684\u524d\u63d0\u4e0b\uff0c\u7d66\u9019\u6b3e\u6b7b\u900f\u4e86\u7684 App \u63db\u4e0a\u4e00\u9846\u73fe\u4ee3\u96f2\u539f\u751f\u5fc3\u81df\uff1f\u4e0b\u4e00\u7bc7\uff0c\u6211\u5011\u804a\u804a Firebase Firestore \u7684\u63db\u5fc3\u6436\u6551\u5be6\u6230\uff01<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5728\u4e0a\u4e00\u7bc7\u88e1\uff0c\u6211\u5011\u628a MVI \u55ae\u5411\u8cc7\u6599\u6d41\u6253\u9020\u5b8c\u7562\uff0c\u6d88\u6ec5\u4e86\u6240\u6709\u72c0\u614b\u6253\u67b6\u8207\u767d\u5c4f\u554f\u984c\u3002\u90a3\u6642\u5019\u6211\u5011\u53ea\u6311\u4e86\u4e00\u689d\u6700\u95dc\u9375\u7684\u6295\u7968 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1298,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[86,169],"tags":[6,172,179,128],"_links":{"self":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/1299"}],"collection":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1299"}],"version-history":[{"count":6,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/1299\/revisions"}],"predecessor-version":[{"id":1311,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/1299\/revisions\/1311"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/media\/1298"}],"wp:attachment":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}