/** Releases all references to given native View. */
 private void dropView(View view) {
   UiThreadUtil.assertOnUiThread();
   if (!mRootTags.get(view.getId())) {
     // For non-root views we notify viewmanager with {@link ViewManager#onDropInstance}
     Assertions.assertNotNull(mTagsToViewManagers.get(view.getId()))
         .onDropViewInstance((ThemedReactContext) view.getContext(), view);
   }
   ViewManager viewManager = mTagsToViewManagers.get(view.getId());
   if (view instanceof ViewGroup && viewManager instanceof ViewGroupManager) {
     ViewGroup viewGroup = (ViewGroup) view;
     ViewGroupManager viewGroupManager = (ViewGroupManager) viewManager;
     for (int i = viewGroupManager.getChildCount(viewGroup) - 1; i >= 0; i--) {
       View child = viewGroupManager.getChildAt(viewGroup, i);
       if (mTagsToViews.get(child.getId()) != null) {
         dropView(child);
       }
     }
     viewGroupManager.removeAllViews(viewGroup);
   }
   mTagsToViews.remove(view.getId());
   mTagsToViewManagers.remove(view.getId());
 }
  private static String constructManageChildrenErrorMessage(
      ViewGroup viewToManage,
      ViewGroupManager viewManager,
      @Nullable int[] indicesToRemove,
      @Nullable ViewAtIndex[] viewsToAdd,
      @Nullable int[] tagsToDelete) {
    StringBuilder stringBuilder = new StringBuilder();

    stringBuilder.append("View tag:" + viewToManage.getId() + "\n");
    stringBuilder.append("  children(" + viewManager.getChildCount(viewToManage) + "): [\n");
    for (int index = 0; index < viewManager.getChildCount(viewToManage); index += 16) {
      for (int innerOffset = 0;
          ((index + innerOffset) < viewManager.getChildCount(viewToManage)) && innerOffset < 16;
          innerOffset++) {
        stringBuilder.append(
            viewManager.getChildAt(viewToManage, index + innerOffset).getId() + ",");
      }
      stringBuilder.append("\n");
    }
    stringBuilder.append(" ],\n");
    if (indicesToRemove != null) {
      stringBuilder.append("  indicesToRemove(" + indicesToRemove.length + "): [\n");
      for (int index = 0; index < indicesToRemove.length; index += 16) {
        for (int innerOffset = 0;
            ((index + innerOffset) < indicesToRemove.length) && innerOffset < 16;
            innerOffset++) {
          stringBuilder.append(indicesToRemove[index + innerOffset] + ",");
        }
        stringBuilder.append("\n");
      }
      stringBuilder.append(" ],\n");
    }
    if (viewsToAdd != null) {
      stringBuilder.append("  viewsToAdd(" + viewsToAdd.length + "): [\n");
      for (int index = 0; index < viewsToAdd.length; index += 16) {
        for (int innerOffset = 0;
            ((index + innerOffset) < viewsToAdd.length) && innerOffset < 16;
            innerOffset++) {
          stringBuilder.append(
              "["
                  + viewsToAdd[index + innerOffset].mIndex
                  + ","
                  + viewsToAdd[index + innerOffset].mTag
                  + "],");
        }
        stringBuilder.append("\n");
      }
      stringBuilder.append(" ],\n");
    }
    if (tagsToDelete != null) {
      stringBuilder.append("  tagsToDelete(" + tagsToDelete.length + "): [\n");
      for (int index = 0; index < tagsToDelete.length; index += 16) {
        for (int innerOffset = 0;
            ((index + innerOffset) < tagsToDelete.length) && innerOffset < 16;
            innerOffset++) {
          stringBuilder.append(tagsToDelete[index + innerOffset] + ",");
        }
        stringBuilder.append("\n");
      }
      stringBuilder.append(" ]\n");
    }

    return stringBuilder.toString();
  }