【问题标题】:React native exception: The specified child already has a parent.反应原生异常:指定的孩子已经有一个父母。
【发布时间】:2016-09-16 16:05:31
【问题描述】:

我收到以下由 React Native 触发的错误。我很确定它链接到我正在使用的自定义视图。

视图由一些 C++ 代码(通过 OpenGL)生成,该代码被添加到 ViewGroup,然后合并到 React Native 视图中。应用程序第一次加载时,一切都很好。但是,当某些数据发生变化时,React 似乎想要重新加载视图,并创建一个新的视图实例。我正在检查视图是否有父视图,如果有,则在返回视图之前将其删除。但是,在用户选择新数据后,就在视图即将更新时,崩溃发生了。

ViewManager 代码如下:

public class ReactJuceViewManager extends SimpleViewManager<JuceViewHolder> {

    public static final String REACT_CLASS = "ReactJuceView";
    private ReactApplicationContext reactContext;

    public ReactJuceViewManager(ReactApplicationContext reactContext)
    {
        super();
        this.reactContext = reactContext;
    }

    @Override
    public String getName()
    {
        return REACT_CLASS;
    }

    @Override
    protected JuceViewHolder createViewInstance(ThemedReactContext themedReactContext) {

        JuceBridge juceBridge = JuceBridge.getInstance(); 
        //JuceBridge manages the a HashMap of `JuceViewHolder`s, never deleting them once created

        Log.d("ReactJuceViewManager", "createViewInstance");
        JuceViewHolder v = juceBridge.getViewForComponent("Tuner", themedReactContext);

        Log.d("JuceViewHolder", v.getTag().toString());
        ViewGroup parent = (ViewGroup) v.getParent();
        if (parent != null)
        {
            Log.d("ReactJuceViewManager", "JuceViewHolder parent: " + v.getParent().toString());
            // Remove from parent
            Log.i("ReactJuceViewManager", "Removing JuceViewHolder instance from previous parent");
            parent.removeView(v);
        }
        else
        {
            Log.d("ReactJuceViewManager", "JuceViewHolder parent: null");
        }

        return v;
    }

}

.. 这是堆栈跟踪:

E/unknown:React: Exception in native call from JS
                                                                       java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
                                                                           at android.view.ViewGroup.addViewInner(ViewGroup.java:4309)
                                                                           at android.view.ViewGroup.addView(ViewGroup.java:4145)
                                                                           at android.view.ViewGroup.addView(ViewGroup.java:4086)
                                                                           at com.facebook.react.views.view.ReactViewManager.addView(ReactViewManager.java:196)
                                                                           at com.facebook.react.views.view.ReactViewManager.addView(ReactViewManager.java:39)
                                                                           at com.facebook.react.uimanager.NativeViewHierarchyManager.manageChildren(NativeViewHierarchyManager.java:384)
                                                                           at com.facebook.react.uimanager.UIViewOperationQueue$ManageChildrenOperation.execute(UIViewOperationQueue.java:175)
                                                                           at com.facebook.react.uimanager.UIViewOperationQueue$2.run(UIViewOperationQueue.java:782)
                                                                           at com.facebook.react.uimanager.UIViewOperationQueue.flushPendingBatches(UIViewOperationQueue.java:829)
                                                                           at com.facebook.react.uimanager.UIViewOperationQueue.access$1500(UIViewOperationQueue.java:44)
                                                                           at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:868)
                                                                           at com.facebook.react.uimanager.GuardedChoreographerFrameCallback.doFrame(GuardedChoreographerFrameCallback.java:32)
                                                                           at com.facebook.react.uimanager.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:131)
                                                                           at android.view.Choreographer$CallbackRecord.run(Choreographer.java:856)
                                                                           at android.view.Choreographer.doCallbacks(Choreographer.java:670)
                                                                           at android.view.Choreographer.doFrame(Choreographer.java:603)
                                                                           at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
                                                                           at android.os.Handler.handleCallback(Handler.java:739)
                                                                           at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                           at android.os.Looper.loop(Looper.java:148)
                                                                           at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

【问题讨论】:

    标签: android react-native


    【解决方案1】:

    我遇到了类似的问题,如果视图已经存在,我通过删除自定义视图的父级来使其正常工作。

    不过,您可能应该在 createViewInstance 上返回一个新组件。

    static CustomView customView;
    
    @Override
    public CustomView createViewInstance(@NonNull ThemedReactContext reactContext) {
        if (customView == null) {
            customView = new CustomView(reactContext);
        } else {
            ViewGroup parent = (ViewGroup) customView.getParent();
            if (parent != null) {
                parent.removeView(customView);
            }
        }
        return customView;
    }
    

    【讨论】:

      【解决方案2】:

      我更改了 JuceBridge 存储对组件的引用的方式 - 存储 ComponentPeerViews 而不是 ViewJuceViewHolder

      (见我的fork of JUCE

      然后我访问了 ComponentPeerView 的父级,这解决了我的问题:

      protected ReactJuceView createViewInstance(ThemedReactContext themedReactContext) {
          JuceBridge juceBridge = JuceBridge.getInstance();
          juceBridge.setActivityContext(themedReactContext);
      
          ReactJuceView v = new ReactJuceView(themedReactContext);
      
          JuceBridge.ComponentPeerView componentPeerView = juceBridge.getPeerViewForComponent("MainComponent");
          if (componentPeerView != null) {
      
              Log.d ("ReactJuceViewManager", "Got componentPeerView");
              ViewGroup parent = (ViewGroup) componentPeerView.getParent();
              if (parent != null) {
      
                  parent.removeView(componentPeerView);
              }
              v.addView(componentPeerView);
              Log.d( "ReactJuceViewManager", "About to attachOpenGlContext");
              MainActivity.attachOpenGLContext("MainComponent");
          }
          else
              Log.d("ReactJuceViewManager", "componentPeerView is null");
      
          return v;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-21
        • 2021-06-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多