React Native Firebase Release版APK无法显示Firestore数据问题
问题环境配置
buildToolsVersion = 32 minSdkVersion = 24 compileSdkVersion = 32 targetSdkVersion = 32 react-native = 0.68.1 @react-native-firebase/app、@react-native-firebase/firestore 版本 = 15.1.1 测试覆盖Android 11、12系统:Android 11下运行正常
问题现象
从Firebase Firestore拉取数据后存入数组类型state,通过组件渲染时,Release签名APK无法展示列表数据;该问题仅在Release包出现,Debug调试环境下所有功能运行完全正常。
涉及的业务代码:
- 状态定义
const [prods, setProds] = useState([]); const [tipeprods, setTipeProds] = useState([]);
- 数据拉取逻辑
firestore().collection('Products').onSnapshot(querySnpshot => { const products = []; querySnpshot.docs.forEach(doc => { products.push(doc.data()); }); setProdFilter(products); setProds(products); });
- FlatList渲染组件
<FlatList data={prodFilter} extraData={prodFilter} renderItem={productsAll} contentContainerStyle={{paddingHorizontal: 10, paddingBottom: 30}} />
- 列表项渲染函数
const productsAll = ({item}) => { return ( <TouchableOpacity style={{ marginBottom: 20, elevation: 20, }} onPress={() => handlePress(item, 'ProdsScreen')}> <View style={{ marginBottom: 10, width: '100%', backgroundColor: 'white', justifyContent: 'center', flexDirection: 'row', borderRadius: 20 }}> <Image source={{uri: item.image}} resizeMode="cover" style={{width: '40%', height: 200, borderRadius: 20}} /> <View style={{ position: 'absolute', bottom: 0, height: 50, width: 80, backgroundColor: 'white', borderTopRightRadius: 20, borderTopLeftRadius: 20, alignItems: 'center', justifyContent: 'center', }}> <Text style={{fontWeight: 'bold'}}>{item.volume}</Text> </View> </View> <Text style={{ fontWeight: 'bold', fontSize: 20, fontVariant: ['small-caps'], color: '#3C2B58', }}> {item.product_name} </Text> </TouchableOpacity> ); };
根本原因
两个问题叠加导致该异常:
- Android Release包默认开启ProGuard代码混淆,项目未配置React Native Firebase对应的混淆保留规则,Firestore SDK内部的类、属性映射方法被混淆重命名,JS层无法正常读取返回对象的字段值
- React Native 0.68版本默认内置Hermes引擎,Release模式下Hermes会开启字节码优化,直接将Firestore返回的原生层对象存入state时,会出现属性访问丢失的问题;Debug模式下Hermes运行在未优化状态,因此不会触发该问题
修复步骤
按顺序操作即可解决问题:
- 补充ProGuard混淆规则
打开Android项目路径下的android/app/proguard-rules.pro文件,在末尾追加以下规则:
# React Native Firebase 混淆保留规则 -keep class io.invertase.firebase.** { *; } -dontwarn io.invertase.firebase.** # 保留Firestore核心类与属性映射方法不被混淆 -keep class com.google.firebase.firestore.** { *; } -keepclassmembers class * { @com.google.firebase.firestore.PropertyName *; }
- 显式序列化Firestore返回数据
修改数据拉取逻辑,不要直接将doc.data()返回的原生对象存入state,手动映射业务需要的字段生成纯JS对象,规避Hermes优化导致的属性访问异常:
firestore().collection('Products').onSnapshot(querySnpshot => { const products = []; querySnpshot.docs.forEach(doc => { const rawData = doc.data(); products.push({ id: doc.id, image: rawData.image, volume: rawData.volume, product_name: rawData.product_name, // 此处补充所有业务用到的其他字段 }); }); setProdFilter(products); setProds(products); });
- 给FlatList补充keyExtractor属性
修改FlatList组件代码,添加key提取规则,避免Release模式下列表项key重复导致的渲染异常:
<FlatList data={prodFilter} extraData={prodFilter} renderItem={productsAll} keyExtractor={item => item.id} contentContainerStyle={{paddingHorizontal: 10, paddingBottom: 30}} />
- 清理构建缓存重新打包
在项目根目录执行以下命令清理旧构建产物,重新打Release包验证即可:
cd android && ./gradlew clean cd .. && npx react-native run-android --variant=release
内容的提问来源于stack exchange,提问作者Xixo
相关产品推荐
相关产品推荐

