Merge change 5397 into donut

* changes:
  Fixes #1943915. Prevents circular dependency exception when using several NO_ID views.
This commit is contained in:
Android (Google) Code Review
2009-06-25 13:32:52 -07:00

View File

@ -41,6 +41,7 @@ import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.HashSet; import java.util.HashSet;
import java.util.ArrayList;
/** /**
* A Layout where the positions of the children can be described in relation to each other or to the * A Layout where the positions of the children can be described in relation to each other or to the
@ -766,14 +767,14 @@ public class RelativeLayout extends ViewGroup {
private View getRelatedView(int[] rules, int relation) { private View getRelatedView(int[] rules, int relation) {
int id = rules[relation]; int id = rules[relation];
if (id != 0) { if (id != 0) {
DependencyGraph.Node node = mGraph.mNodes.get(id); DependencyGraph.Node node = mGraph.mKeyNodes.get(id);
if (node == null) return null; if (node == null) return null;
View v = node.view; View v = node.view;
// Find the first non-GONE view up the chain // Find the first non-GONE view up the chain
while (v.getVisibility() == View.GONE) { while (v.getVisibility() == View.GONE) {
rules = ((LayoutParams) v.getLayoutParams()).getRules(); rules = ((LayoutParams) v.getLayoutParams()).getRules();
node = mGraph.mNodes.get((rules[relation])); node = mGraph.mKeyNodes.get((rules[relation]));
if (node == null) return null; if (node == null) return null;
v = node.view; v = node.view;
} }
@ -1108,11 +1109,16 @@ public class RelativeLayout extends ViewGroup {
} }
private static class DependencyGraph { private static class DependencyGraph {
/**
* List of all views in the graph.
*/
private ArrayList<Node> mNodes = new ArrayList<Node>();
/** /**
* List of nodes in the graph. Each node is identified by its * List of nodes in the graph. Each node is identified by its
* view id (see View#getId()). * view id (see View#getId()).
*/ */
private SparseArray<Node> mNodes = new SparseArray<Node>(); private SparseArray<Node> mKeyNodes = new SparseArray<Node>();
/** /**
* Temporary data structure used to build the list of roots * Temporary data structure used to build the list of roots
@ -1124,14 +1130,15 @@ public class RelativeLayout extends ViewGroup {
* Clears the graph. * Clears the graph.
*/ */
void clear() { void clear() {
final SparseArray<Node> nodes = mNodes; final ArrayList<Node> nodes = mNodes;
final int count = nodes.size(); final int count = nodes.size();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
nodes.valueAt(i).release(); nodes.get(i).release();
} }
nodes.clear(); nodes.clear();
mKeyNodes.clear();
mRoots.clear(); mRoots.clear();
} }
@ -1141,7 +1148,14 @@ public class RelativeLayout extends ViewGroup {
* @param view The view to be added as a node to the graph. * @param view The view to be added as a node to the graph.
*/ */
void add(View view) { void add(View view) {
mNodes.put(view.getId(), Node.acquire(view)); final int id = view.getId();
final Node node = Node.acquire(view);
if (id != View.NO_ID) {
mKeyNodes.put(id, node);
}
mNodes.add(node);
} }
/** /**
@ -1192,20 +1206,21 @@ public class RelativeLayout extends ViewGroup {
* @return A list of node, each being a root of the graph * @return A list of node, each being a root of the graph
*/ */
private LinkedList<Node> findRoots(int[] rulesFilter) { private LinkedList<Node> findRoots(int[] rulesFilter) {
final SparseArray<Node> nodes = mNodes; final SparseArray<Node> keyNodes = mKeyNodes;
final ArrayList<Node> nodes = mNodes;
final int count = nodes.size(); final int count = nodes.size();
// Find roots can be invoked several times, so make sure to clear // Find roots can be invoked several times, so make sure to clear
// all dependents and dependencies before running the algorithm // all dependents and dependencies before running the algorithm
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
final Node node = nodes.valueAt(i); final Node node = nodes.get(i);
node.dependents.clear(); node.dependents.clear();
node.dependencies.clear(); node.dependencies.clear();
} }
// Builds up the dependents and dependencies for each node of the graph // Builds up the dependents and dependencies for each node of the graph
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
final Node node = nodes.valueAt(i); final Node node = nodes.get(i);
final LayoutParams layoutParams = (LayoutParams) node.view.getLayoutParams(); final LayoutParams layoutParams = (LayoutParams) node.view.getLayoutParams();
final int[] rules = layoutParams.mRules; final int[] rules = layoutParams.mRules;
@ -1217,7 +1232,7 @@ public class RelativeLayout extends ViewGroup {
final int rule = rules[rulesFilter[j]]; final int rule = rules[rulesFilter[j]];
if (rule > 0) { if (rule > 0) {
// The node this node depends on // The node this node depends on
final Node dependency = nodes.get(rule); final Node dependency = keyNodes.get(rule);
if (dependency == node) { if (dependency == node) {
throw new IllegalStateException("A view cannot have a dependency" + throw new IllegalStateException("A view cannot have a dependency" +
" on itself"); " on itself");
@ -1238,7 +1253,7 @@ public class RelativeLayout extends ViewGroup {
// Finds all the roots in the graph: all nodes with no dependencies // Finds all the roots in the graph: all nodes with no dependencies
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
final Node node = nodes.valueAt(i); final Node node = nodes.get(i);
if (node.dependencies.size() == 0) roots.add(node); if (node.dependencies.size() == 0) roots.add(node);
} }