Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reusing TreeNode structure #25

Open
disovi opened this issue Jul 16, 2015 · 14 comments
Open

reusing TreeNode structure #25

disovi opened this issue Jul 16, 2015 · 14 comments

Comments

@disovi
Copy link

disovi commented Jul 16, 2015

I've created TreeNode structure and used it with AndroidTreeView. When I'm trying to reuse this structure with new AndroidTreeView I receive error

Caused by: 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:3936)
            at android.view.ViewGroup.addView(ViewGroup.java:3786)
            at android.view.ViewGroup.addView(ViewGroup.java:3727)
            at android.view.ViewGroup.addView(ViewGroup.java:3700)
            at com.unnamed.b.atv.view.AndroidTreeView.addNode(AndroidTreeView.java:228)
            at com.unnamed.b.atv.view.AndroidTreeView.expandNode(AndroidTreeView.java:210)
            at com.unnamed.b.atv.view.AndroidTreeView.getView(AndroidTreeView.java:106)
            at com.unnamed.b.atv.view.AndroidTreeView.getView(AndroidTreeView.java:111)

The problem is in ViewHolder. Before reusing ViewHolder we should set mView to null, but it is impossible now.

For now I have to use such hack

void cleanTreeNodes(List<TreeNode> treeNodes) {
        for (TreeNode treeNode : treeNodes) {
            TreeNode.BaseNodeViewHolder viewHolder = treeNode.getViewHolder();
            try {
                TreeNode.BaseNodeViewHolder viewHolder2 = viewHolder.getClass().getDeclaredConstructor(Context.class).newInstance(this);
                treeNode.setViewHolder(viewHolder2);
                viewHolder2.setContainerStyle(viewHolder.getContainerStyle());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            cleanTreeNodes(treeNode.getChildren());
        }
    }
@bmelnychuk
Copy link
Owner

You can not reuse TreeNode structure, is it possible for you to re-create that structure?

@disovi
Copy link
Author

disovi commented Jul 20, 2015

yes it is possible, but why can't we just add a method for cleaning views?

@dogauzun
Copy link

Can you explain this bug a little more? I have the same problem and I do not think I understand the issue. I am trying to fix the issue with something like

((ViewGroup) treeView.getParent()).removeView(treeView);

@disovi
Copy link
Author

disovi commented Jul 24, 2015

@dogauzun, my idea was to force viewHolder generate new view for each node. Your way is simpler. If you want to reuse views, which have been generated already, you can remove views of first level nodes from parent layout, something like this:

((ViewGroup)mRoot.getChildren().get(0).getViewHolder().getView().getParent()).removeAllViews();

@Odaym
Copy link

Odaym commented Aug 10, 2015

I solved this with the following code:

    //Used this treeView previously
    if (treeView != null)
        containerView.removeAllViews();

    treeView = AndroidTreeView(getActivity(), root);
    //...etc...
    containerView.addView(treeView.getView());

works just fine

@dogauzun
Copy link

None of the above solutions are working for me. I am using a fragment and I initialize the treeview when i fetch some data from the network. It works fine for the first time but getView method throws an IllegalState exception on the second time. I am recreating Treenodes and viewholders from scratch each time.

@nmorteza
Copy link

nmorteza commented Mar 6, 2016

I solved this with the following code:
if(tView == null) {
Log.d("aaa","tView is null");
tView = new AndroidTreeView(getActivity(), root);
tView.setDefaultAnimation(true);
tView.setDefaultContainerStyle(R.style.TreeNodeStyleCustom);
tView.setDefaultViewHolder(IconTreeItemHolder.class);
tView.setDefaultNodeClickListener(nodeClickListener);
tView.setDefaultNodeLongClickListener(nodeLongClickListener);
root=TreeNode.root();

        // ((ViewGroup) containerView.getParent()).removeView(tView.getView());

        containerView.addView(tView.getView());
    }else{
        Log.d("aaa", "tView is not null");

        containerView.removeAllViews();
        tView = new AndroidTreeView(getActivity(), root);
        tView.setDefaultAnimation(true);
        tView.setDefaultContainerStyle(R.style.TreeNodeStyleCustom);
        tView.setDefaultViewHolder(IconTreeItemHolder.class);
        tView.setDefaultNodeClickListener(nodeClickListener);
        tView.setDefaultNodeLongClickListener(nodeLongClickListener);
        root=TreeNode.root();

        containerView.addView(tView.getView());
    }

@stay4cold
Copy link

@dogauzun I have the same issue with you. Have you fixed it now?

@dogauzun
Copy link

dogauzun commented May 4, 2016

I solved my problem with moving my tree initialization method from onCreateView to onStart method in my fragment. I was trying to avoid initializing my tree everytime my fragment becomes visible but in my use case the tree structure is actually not that big so I stopped trying to do that.

@sanjutagra
Copy link

None of the above solutions are working for me. Has anybody found the right solution ?

@nmorteza
Copy link

ok

On Wed, May 4, 2016 at 2:19 PM, ministorm notifications@github.com wrote:

@dogauzun https://github.com/dogauzun I have the same issue with you.
Have you fixed it now?


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#25 (comment)

@simkis
Copy link

simkis commented Mar 9, 2017

private void clearViewHolders(List<TreeNode> treeNodes) {
    for (TreeNode node : treeNodes) {
        if (node.getViewHolder() instanceof TreeStepViewHolder) {
            node.setViewHolder(null);
            TreeStepViewHolder treeStepViewHolder = new TreeStepViewHolder(getContext());
            treeStepViewHolder.setContainerStyle(R.style.TreeNodeStyleCustom);
            node.setViewHolder(treeStepViewHolder);
        } else if (node.getViewHolder() instanceof TreeFailureViewHolder) {
            node.setViewHolder(null);
            TreeFailureViewHolder treeFailureViewHolder = new TreeFailureViewHolder(getContext());
            treeFailureViewHolder.setContainerStyle(R.style.TreeNodeStyleCustom);
            node.setViewHolder(treeFailureViewHolder);
        }
        clearViewHolders(node.getChildren());
    }
}

This works for me.

@gyqsophila
Copy link

gyqsophila commented Mar 20, 2017

Thank you all of above, help me solving the problem of refresh tree node with data changed.
here is my code , if anyone need:

if (layout != null) {//layout is the view you inflated in method createView,keep a reference to class field
            layout.removeAllViews();
            TreeNode newroot = TreeNode.root();
            fillTreeData(newroot, contextEvents);
            AndroidTreeView newTree = new AndroidTreeView(getActivity(), newroot);
            newTree.setDefaultAnimation(true);
            newTree.setDefaultViewHolder(MyTreeViewHolder.class);
            newTree.setDefaultContainerStyle(R.style.TreeNodeStyle);
            layout.addView(newTree.getView());
        }

these code can be called outside of method createView in fragment.

@TTLZZU
Copy link

TTLZZU commented Apr 14, 2019

I have same question, I solved my problem with fixing IconTreeItemHolder.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants