You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设置userInterfaceStyle为dark时Expo SDK51安卓应用启动崩溃

问题:Expo SDK 51设置强制深色模式后安卓启动崩溃

基于Expo SDK 51开发的应用,为强制使用深色配色方案,在app.config.js中设置了userInterfaceStyle: "dark",iOS端可正常运行并生效,但安卓开发构建版本启动时崩溃,报错Must be called from main thread。Expo Doctor检测无任何问题,相关配置及依赖如下:

应用配置代码(app.config.js)

import { dirname, join } from "node:path";

import type { ConfigContext, ExpoConfig } from "@expo/config";

const INTER_FONTS = [
  "100Thin",
  "200ExtraLight",
  "300Light",
  "400Regular",
  "500Medium",
  "600SemiBold",
  "700Bold",
  "800ExtraBold",
  "900Black",
].map((name) =>
  join(
    dirname(require.resolve("@expo-google-fonts/inter")),
    `Inter_${name}.ttf`,
  ),
);

const DIN_NEXT_LT_PRO_FONTS = ["Medium", "Bold", "Heavy"].map((name) =>
  require.resolve(`./assets/fonts/din-next-lt-pro/DINNextLTPro-${name}.ttf`),
);

export default ({ config }: ConfigContext): ExpoConfig => ({
  ...config,
  owner: "<REDACTED>",
  name: "<REDACTED>",
  slug: "<REDACTED>",
  version: "1.0.0",
  orientation: "portrait",
  icon: "./assets/images/icon.png",
  scheme: "<REDACTED>",
  userInterfaceStyle: "dark",
  splash: {
    image: "./assets/images/splash.png",
    resizeMode: "contain",
    backgroundColor: "#03161C",
  },
  ios: {
    supportsTablet: false,
    bundleIdentifier: "com.<REDACTED>.app",
  },
  android: {
    adaptiveIcon: {
      foregroundImage: "./assets/images/adaptive-icon/foreground.png",
      backgroundImage: "./assets/images/adaptive-icon/background.png",
      backgroundColor: "#04151C",
    },
    package: "com.<REDACTED>.app",
  },
  web: {
    bundler: "metro",
    output: "static",
    favicon: "./assets/images/favicon.png",
  },
  plugins: [
    "expo-router",
    [
      "expo-font",
      {
        fonts: [...INTER_FONTS, ...DIN_NEXT_LT_PRO_FONTS],
      },
    ],
  ],
  experiments: {
    typedRoutes: true,
  },
  extra: {
    eas: {
      projectId: "<REDACTED>",
    },
  },
});

依赖配置(package.json)

{
  "name": "mobile-client",
  "main": "expo-router/entry",
  "version": "1.0.0",
  "scripts": {
    "start": "expo start",
    "android": "expo run:android",
    "ios": "expo run:ios",
    "web": "expo start --web",
    "eas-build-post-install": "yarn workspaces foreach --parallel --interlaced --recursive --from mobile-client --exclude mobile-client run build"
  },
  "installConfig": {
    "hoistingLimits": "workspaces"
  },
  "dependencies": {
    "@expo-google-fonts/inter": "^0.2.3",
    "@expo/html-elements": "^0.10.1",
    "@expo/vector-icons": "^14.0.2",
    "@gluestack-ui/accordion": "^1.0.7",
    "@gluestack-ui/actionsheet": "^0.2.45",
    "@gluestack-ui/alert": "^0.1.15",
    "@gluestack-ui/alert-dialog": "^0.1.31",
    "@gluestack-ui/avatar": "^0.1.17",
    "@gluestack-ui/button": "^1.0.7",
    "@gluestack-ui/checkbox": "^0.1.32",
    "@gluestack-ui/divider": "^0.1.9",
    "@gluestack-ui/fab": "^0.1.21",
    "@gluestack-ui/form-control": "^0.1.18",
    "@gluestack-ui/icon": "^0.1.22",
    "@gluestack-ui/image": "^0.1.10",
    "@gluestack-ui/input": "^0.1.31",
    "@gluestack-ui/link": "^0.1.22",
    "@gluestack-ui/menu": "^0.2.36",
    "@gluestack-ui/modal": "^0.1.34",
    "@gluestack-ui/nativewind-utils": "patch:@gluestack-ui/nativewind-utils@npm%3A1.0.23#~/.yarn/patches/@gluestack-ui-nativewind-utils-npm-1.0.23-7232dc7123.patch",
    "@gluestack-ui/overlay": "^0.1.15",
    "@gluestack-ui/popover": "^0.1.41",
    "@gluestack-ui/pressable": "^0.1.16",
    "@gluestack-ui/progress": "^0.1.17",
    "@gluestack-ui/radio": "^0.1.33",
    "@gluestack-ui/select": "^0.1.29",
    "@gluestack-ui/slider": "^0.1.25",
    "@gluestack-ui/spinner": "^0.1.14",
    "@gluestack-ui/switch": "^0.1.22",
    "@gluestack-ui/textarea": "^0.1.23",
    "@gluestack-ui/toast": "^1.0.7",
    "@gluestack-ui/tooltip": "^0.1.34",
    "@legendapp/motion": "^2.4.0",
    "@react-native-masked-view/masked-view": "0.3.1",
    "@react-navigation/bottom-tabs": "^6",
    "@react-navigation/native": "^6",
    "expo": "~51.0.39",
    "expo-blur": "~13.0.2",
    "expo-constants": "~16.0.2",
    "expo-dev-client": "~4.0.29",
    "expo-font": "~12.0.10",
    "expo-haptics": "~13.0.1",
    "expo-linear-gradient": "~13.0.2",
    "expo-linking": "~6.3.1",
    "expo-router": "~3.5.24",
    "expo-splash-screen": "~0.27.7",
    "expo-status-bar": "~1.12.1",
    "expo-symbols": "~0.1.5",
    "expo-system-ui": "~3.0.7",
    "expo-web-browser": "~13.0.3",
    "lucide-react-native": "^0.455.0",
    "metro-config": "^0.80.0",
    "nativewind": "4.0.36",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-native": "0.74.5",
    "react-native-gesture-handler": "~2.16.1",
    "react-native-reanimated": "~3.10.1",
    "react-native-safe-area-context": "4.10.5",
    "react-native-screens": "3.31.1",
    "react-native-svg": "15.2.0",
    "react-native-svg-transformer": "^1.5.0",
    "react-native-web": "~0.19.13",
    "shared": "workspace:^",
    "tailwind-merge": "^2.5.4",
    "tailwindcss": "^3.4.14",
    "ts-node": "^10.9.2"
  },
  "devDependencies": {
    "@babel/core": "^7.25.2",
    "@types/jest": "^29.5.12",
    "@types/node": "^22.9.0",
    "@types/react": "~18.2.79",
    "@types/react-test-renderer": "^18.2.0",
    "jest": "^29.2.1",
    "jest-expo": "~51.0.4",
    "react-test-renderer": "18.2.0",
    "typescript": "~5.3.3"
  }
}

解决方案

该问题是Expo SDK 51在安卓端设置全局userInterfaceStyle时的线程调用bug,可通过以下方式解决:

方案1:移除全局配置,用代码动态设置深色模式

删除app.config.js中的userInterfaceStyle: "dark",在应用入口(如_layout.tsx)添加以下代码:

import { useEffect } from 'react';
import { Appearance } from 'react-native';
import { StatusBar } from 'expo-status-bar';

export default function RootLayout() {
  // 强制设置深色模式
  useEffect(() => {
    Appearance.setColorScheme('dark');
  }, []);

  return (
    <>
      {/* 原有布局内容 */}
      <StatusBar style="light" />
    </>
  );
}

方案2:升级/降级Expo SDK版本

若坚持使用全局配置,可升级到Expo SDK 52或降级到SDK 50,该bug在这些版本中已修复。

方案3:修改安卓原生代码(仅必要时使用)

手动修改android/app/src/main/java/com/[你的包名]/MainActivity.kt,确保UI模式设置在主线程执行:

import android.os.Bundle
import androidx.appcompat.app.AppCompatDelegate
import expo.modules.ReactActivity

class MainActivity : ReactActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    runOnUiThread {
      AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
    }
    super.onCreate(savedInstanceState)
  }

  // 保留原有其他代码
}

验证

修改后重新执行expo run:android,安卓应用即可正常启动并保持深色模式。

内容的提问来源于stack exchange,提问作者Fez Vrasta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 09:05:57