React Native集成Android原生组件构建失败:空对象引用错误求助
React Native集成Android原生组件空指针问题修复方案
我是React Native新手,按官方文档集成Android原生组件后,应用无法构建,报错:Attempt to invoke interface method 'int java.util.List.size()' on a null object reference。原项目未修改时可在Pixel 4a正常运行,排查多日无果,以下是代码及修复建议。
核心错误原因
报错源于某个List对象为null时被调用了size()方法,结合代码排查,主要问题出在MyPackage的createNativeModules方法返回null,此外还有多处潜在空指针风险。
修复步骤
1. 修复MyPackage的createNativeModules方法
React Native要求该方法必须返回List对象(即使是空列表),返回null会触发框架调用size()时的空指针:
package com.testapp; import androidx.annotation.NonNull; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.ArrayList; import java.util.List; public class MyPackage implements ReactPackage { @NonNull @Override public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactApplicationContext) { // 返回空列表而非null return new ArrayList<>(); } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { List<ViewManager> VM = new ArrayList<>(); VM.add(new MyViewManager(reactContext)); return VM; } }
2. 给MyViewManager的receiveCommand添加参数非空判断
JS传递的args可能为null,直接调用args.getInt(0)会触发空指针:
@Override public void receiveCommand( @NonNull FrameLayout root, String commandId, @Nullable ReadableArray args ) { super.receiveCommand(root, commandId, args); // 添加args非空判断 if (args == null || args.size() == 0) { return; } int reactNativeViewId = args.getInt(0); int commandIdInt = Integer.parseInt(commandId); switch (commandIdInt) { case COMMAND_CREATE: createFragment(root, reactNativeViewId); break; default: {} } }
3. 初始化propWidth和propHeight的默认值
未设置style时,这两个变量默认值为0,可能导致布局异常:
public class MyViewManager extends ViewGroupManager<FrameLayout> { public static final String REACT_CLASS = "MyViewManager"; public final int COMMAND_CREATE = 1; // 初始化默认宽高,避免measure时用0 private int propWidth = 200; private int propHeight = 200; // 其他代码不变... }
4. 在createFragment中添加非空判断
parentView和activity可能为null,需提前判断避免崩溃:
public void createFragment(FrameLayout root, int reactNativeViewId) { ViewGroup parentView = (ViewGroup) root.findViewById(reactNativeViewId); // 检查parentView是否存在 if (parentView == null) { return; } setupLayout(parentView); FragmentActivity activity = (FragmentActivity) reactContext.getCurrentActivity(); // 检查activity是否有效 if (activity == null) { return; } final MyFragment myFragment = new MyFragment(); activity.getSupportFragmentManager() .beginTransaction() .replace(reactNativeViewId, myFragment, String.valueOf(reactNativeViewId)) .commit(); }
5. 优化setupLayout的回调逻辑
原代码中Choreographer的回调会无限执行,导致性能问题,改为只执行一次:
public void setupLayout(View view) { Choreographer.FrameCallback callback = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { manuallyLayoutChildren(view); view.getViewTreeObserver().dispatchOnGlobalLayout(); // 执行后移除回调 Choreographer.getInstance().removeFrameCallback(this); } }; Choreographer.getInstance().postFrameCallback(callback); }
内容的提问来源于stack exchange,提问作者Shrini
相关产品推荐
相关产品推荐

