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

Expo中预填充SQLite数据库连接异常问题排查

问题诊断与解决方案

你的问题核心出在Android平台的路径处理、Asset资源预加载逻辑缺失,以及缺少数据库存在性检查这几个方面,以下是针对性的修正方案:

1. 修复SQLite目录路径的斜杠问题

你代码中创建目录的写法${FileSystem.documentDirectory}SQLite存在隐患:FileSystem.documentDirectory在Android平台结尾自带斜杠(例如/data/user/0/com.yourapp/files/),拼接后会变成/data/user/0/com.yourapp/filesSQLite——这是无效路径,直接导致目录创建失败、数据库无法复制。

推荐使用FileSystem.join统一处理路径,避免斜杠问题:

import * as FileSystem from 'expo-file-system';

const dbDir = FileSystem.join(FileSystem.documentDirectory, 'SQLite');
const dbPath = FileSystem.join(dbDir, 'db_name.db');

2. 补充Asset资源预加载步骤

Asset.fromModule(require('./assets/db_name.db'))仅创建了Asset对象,但Android平台需要先调用await dbAsset.downloadAsync()确保资源已加载到本地,否则直接使用dbAsset.uri可能指向未就绪的资源地址,导致复制失败。

3. 增加数据库存在性检查

每次启动都重复复制数据库,不仅会产生冗余操作,还可能因Android平台文件已存在而触发报错。先检查目标路径是否已有数据库,存在则直接打开即可。

修正后的完整copyDatabase函数

import * as FileSystem from 'expo-file-system';
import * as Asset from 'expo-asset';
import * as SQLite from 'expo-sqlite';

const dbDir = FileSystem.join(FileSystem.documentDirectory, 'SQLite');
const dbPath = FileSystem.join(dbDir, 'db_name.db');

const copyDatabase = async () => {
  // 检查数据库是否已存在
  const fileInfo = await FileSystem.getInfoAsync(dbPath);
  if (fileInfo.exists) {
    console.log('数据库已存在,直接打开');
    return SQLite.openDatabase('db_name.db');
  }

  // 创建SQLite目录
  await FileSystem.makeDirectoryAsync(dbDir, { intermediates: true });

  // 预加载Asset资源
  const dbAsset = Asset.fromModule(require('./assets/db_name.db'));
  await dbAsset.downloadAsync(); // Android平台必须的预加载步骤

  // 复制数据库文件
  await FileSystem.copyAsync({
    from: dbAsset.localUri || dbAsset.uri, // 兼容Android/iOS的URI格式
    to: dbPath,
  });

  console.log('数据库复制完成,路径:', dbPath);
  return SQLite.openDatabase('db_name.db');
};

4. EAS构建额外配置

  • 确保app.json中配置了资源打包规则,让EAS构建时正确包含db文件:
{
  "expo": {
    "assetBundlePatterns": [
      "assets/**/*"
    ]
  }
}
  • 若使用旧版本expo-sqlite,需在app.json中添加文件访问权限:
{
  "expo": {
    "android": {
      "permissions": ["READ_EXTERNAL_STORAGE", "WRITE_EXTERNAL_STORAGE"]
    }
  }
}

5. 修正组件内调用时机

不要在App组件开头同步调用异步函数copyDatabase(),应使用useEffect在组件挂载时执行,避免阻塞渲染:

import { useState, useEffect } from 'react';
import { Text } from 'react-native';

export default function App() {
  const [db, setDb] = useState(null);

  useEffect(() => {
    const initDb = async () => {
      const database = await copyDatabase();
      setDb(database);
    };
    initDb();
  }, []);

  // 等待数据库初始化完成后再渲染业务组件
  if (!db) {
    return <Text>加载中...</Text>;
  }

  return (
    // 你的业务组件内容
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 17:58:13