user8 user8 - 5 months ago 16
Android Question

Variable remains null when should be set

I have a View object and I try to set it. However, it always remains

null
outside the function . Here I try to set it while being passed as a parameter, I also tried with
return
-statement but to no avail. Most probably, because the problem is somewhere else and I just can't see it. Strangely, enough it gets set inside the function, but outside remains null. Code:

private EditText mView = null;

public void findViewByTag(ViewGroup vg, Object obj, View v) {

if (vg == null)
return;

for (int i = 0; i < vg.getChildCount(); i++) {
if (vg.getChildAt(i).getTag() != null) {
if (vg.getChildAt(i).getTag().toString().equals(obj)) {
Log.d("Found", "Yes." + obj.toString());//here it does get found
v = vg.getChildAt(i);
//tested, it is not null HERE
return;
}
}
}
for (int i = 0; i < vg.getChildCount(); i++) {
if (vg.getChildAt(i) instanceof ViewGroup) {
findViewByTag((ViewGroup) vg.getChildAt(i), obj, v);
}
}
}


Then I call it like
findViewbyTag(mViewGroup, "_MyTag", mView)
. Here I find out that
mView == null
.

As a side question, how can I stop the recursion from iterating all my views after having found the one? Is there a way to stop it iterating the other view branches? Probably not, but still.

EDIT:
This also doesn't work out as said in the beginning above.

public View findViewByTag(ViewGroup vg, Object obj) {

if (vg == null)
return null;

for (int i = 0; i < vg.getChildCount(); i++) {
//because some are not set and we don't like NullPtrs
if (vg.getChildAt(i).getTag() != null) {
if (vg.getChildAt(i).getTag().toString().equals(obj)) {
Log.d("Found", "Yes." + obj.toString());

return vg.getChildAt(i);
}
}
}
for (int i = 0; i < vg.getChildCount(); i++) {
if (vg.getChildAt(i) instanceof ViewGroup) {
findViewByTag((ViewGroup) vg.getChildAt(i), obj);
}
}
return null;
}

Answer

I think your two issues are the same problem: the ultimate value of v is from the last call only, not the successful one. The only time you get the desired value is when it's in the last branch of your search.

The main problem is that you don't stop when you find it. Rewrite the logic to do two things:

  1. Return the found item (or NULL) as the functional value (change void to View and drop the v parameter).
  2. Capture this return value inside your loop, and continue only so long as it's NULL. Break when you get a good value. Regardless of your method of loop exit, return the "best" value found (success or failure).

I don't have a JRE to test in here, but let me try a blind hand-edit:

public View findViewByTag(ViewGroup vg, Object obj) {

    result = null

    if (vg == null)
        return null;

    for (int i = 0; i < vg.getChildCount(); i++) {
        //because some are not set and we don't like NullPtrs
        if (vg.getChildAt(i).getTag() != null) {
            if (vg.getChildAt(i).getTag().toString().equals(obj)) {
                Log.d("Found", "Yes." + obj.toString());

                result = vg.getChildAt(i);
            }
        }
    }
    for (int i = 0; i < vg.getChildCount(); i++) {
        if (vg.getChildAt(i) instanceof ViewGroup) {
            result = findViewByTag((ViewGroup) vg.getChildAt(i), obj);
            if (result) break;
        }
    }
    return result;
}

Your previous version failed to return a successful result. You can clean up this logic flow a little, but I tried to keep the changes minimal.

Comments