/** * Add a dependency to this Node. The dependency includes information about the node that this * node is dependency upon and the nature of the dependency. * * @param dependency */ public void addDependency(Dependency dependency) { if (dependencies == null) { dependencies = new ArrayList<Dependency>(); nodeDependencies = new ArrayList<Node>(); } dependencies.add(dependency); if (!nodeDependencies.contains(dependency.node)) { nodeDependencies.add(dependency.node); } Node dependencyNode = dependency.node; if (dependencyNode.nodeDependents == null) { dependencyNode.nodeDependents = new ArrayList<Node>(); } dependencyNode.nodeDependents.add(this); }
@Override public AnimatorSet clone() { final AnimatorSet anim = (AnimatorSet) super.clone(); /* * The basic clone() operation copies all items. This doesn't work very well for * AnimatorSet, because it will copy references that need to be recreated and state * that may not apply. What we need to do now is put the clone in an uninitialized * state, with fresh, empty data structures. Then we will build up the nodes list * manually, as we clone each Node (and its animation). The clone will then be sorted, * and will populate any appropriate lists, when it is started. */ anim.mNeedsSort = true; anim.mTerminated = false; anim.mStarted = false; anim.mPlayingSet = new ArrayList<Animator>(); anim.mNodeMap = new HashMap<Animator, Node>(); anim.mNodes = new ArrayList<Node>(); anim.mSortedNodes = new ArrayList<Node>(); // Walk through the old nodes list, cloning each node and adding it to the new nodemap. // One problem is that the old node dependencies point to nodes in the old AnimatorSet. // We need to track the old/new nodes in order to reconstruct the dependencies in the clone. HashMap<Node, Node> nodeCloneMap = new HashMap<Node, Node>(); // <old, new> for (Node node : mNodes) { Node nodeClone = node.clone(); nodeCloneMap.put(node, nodeClone); anim.mNodes.add(nodeClone); anim.mNodeMap.put(nodeClone.animation, nodeClone); // Clear out the dependencies in the clone; we'll set these up manually later nodeClone.dependencies = null; nodeClone.tmpDependencies = null; nodeClone.nodeDependents = null; nodeClone.nodeDependencies = null; // clear out any listeners that were set up by the AnimatorSet; these will // be set up when the clone's nodes are sorted ArrayList<AnimatorListener> cloneListeners = nodeClone.animation.getListeners(); if (cloneListeners != null) { ArrayList<AnimatorListener> listenersToRemove = null; for (AnimatorListener listener : cloneListeners) { if (listener instanceof AnimatorSetListener) { if (listenersToRemove == null) { listenersToRemove = new ArrayList<AnimatorListener>(); } listenersToRemove.add(listener); } } if (listenersToRemove != null) { for (AnimatorListener listener : listenersToRemove) { cloneListeners.remove(listener); } } } } // Now that we've cloned all of the nodes, we're ready to walk through their // dependencies, mapping the old dependencies to the new nodes for (Node node : mNodes) { Node nodeClone = nodeCloneMap.get(node); if (node.dependencies != null) { for (Dependency dependency : node.dependencies) { Node clonedDependencyNode = nodeCloneMap.get(dependency.node); Dependency cloneDependency = new Dependency(clonedDependencyNode, dependency.rule); nodeClone.addDependency(cloneDependency); } } } return anim; }