Reputation: 707
Today I came across this really interesting situation.
Suppose:
An EditText
is instantiated from XML
.
EditText editText;
editText = findViewByID(R.id.editText_xml_id);
Now, I want to listen for change in focus in the EditText
. So I write the following code:
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in parent" );
}
});
Everything is good up until this point as when change in focus, the Log is triggered.
Now the interesting part: Say, I want to put the same focus listener, but twice! So what I will do is:
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in parent: First callback" );
}
});
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in parent: Second callback" );
}
});
What I had expected was, since editText instance has been set to listen to two instances of View.OnFocusChangeListeners
I thought the results would arrive in both listeners.
But only later I realized that only the latter listener ( which was set at the latest ) sent the actual callback inside onFocuChange();
This means, when the focus was changed, I was expecting :
Log.e("TAG", "Focus Changed in parent: First callback" );
Log.e("TAG", "Focus Changed in parent: Second callback" );
but what I got was :
Log.e("TAG", "Focus Changed in parent: Second callback" );
With a little thought, I think this happened because the first listener that was set in editText was replaced by the latter one. And thus only one TAG was hit. (Please correct me if I'm wrong on this)
On experimenting further, I thought what if I assign editText
to a different EditText
variable and then set two unique listeners to each?
So I did this :
EditText childEditText1;
childEditText1 = editText;
Then I assigned two different listeners:
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in child" );
}
});
childEditText1.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in parent" );
}
});
On changing focus, what I was expecting was both the tags to be hit. This was because now there are two DIFFERENT instances of the same variable, and they each listen to two DIFFERENT listeners. But again, only one was hit. Expectation:
//Expected
Log.e("TAG", "Focus Changed in child" );
Log.e("TAG", "Focus Changed in parent" );
Reality:
//Reality
Log.e("TAG", "Focus Changed in parent" );
What I am guessing is no matter what, both the EditText
instances are pointing to the same memory space ? Or what is it? Because otherwise both the TAGS would have been hit.
Now, this would be as expected if there were some String and its values were being changed. Like:
String str = "hi";
str1 = str;
str1 = str1 + " there";
Log.e("TAG", "str " + str );
Result: hi
Log.e("TAG", "str1 " + str1 );
Result : hi there
But from above experiment, it was like :
Log.e("TAG", "str " + str );
Result: hi there
//which is not the case
And this bugs my mind a lot.
Please explain why this sort of anomaly with EditText and if there is any technical term for this in Java. And do point to any resource or books that explain such better. I'm not new to Android but this definitely is.
Thanks!
Upvotes: 2
Views: 106
Reputation: 11
private EditText editTextone;
private Editext editTexttwo;
editTextone =(EditText) findViewByID(R.id.editText_xml_id_one);
editTexttwo =(EditText) findViewByID(R.id.editText_xml_id_one);
Upvotes: 1
Reputation: 2370
This is a general programming concept.
1- editText.onFocusListener
is null.
2- editText.onFocusListener
is changed by the below block. It now prints the first Log.
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in child" );
}
});
3- editText.onFocusListener
is changed by the below block. It now prints the other Log.
childEditText1.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
Log.e("TAG", "Focus Changed in parent" );
}
});
This is completely different to something like addOnChangeListener
.
The above is a set
function which is different to an add
Function.
Hope this clears it up!
Upvotes: 1
Reputation: 803
First question: the first listener that was set in editText was replaced by the latter one : cause: http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/View.java#6318
//view.java
/**
* Register a callback to be invoked when focus of this view changed.
*
* @param l The callback that will run.
*/
public void setOnFocusChangeListener(OnFocusChangeListener l) {
getListenerInfo().mOnFocusChangeListener = l;
}
ListenerInfo getListenerInfo() {
if (mListenerInfo != null) {
return mListenerInfo;
}
mListenerInfo = new ListenerInfo();
return mListenerInfo;
}
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/View.java#4271 and so u can see , there is only one changelistener could be set . and the second one will replace the first one.
second question: upper answer is quite good.
Upvotes: 2
Reputation: 157457
his was because now there are two DIFFERENT instances of the same variable, and they each listen to two DIFFERENT listeners. But again, only one was hit. Expectation:
you are calling a setter on the same reference. The last one wins (it overrides the previous one)
Please explain why this sort of anomaly with EditText and if there is an y technical term for this in Java.And do point to any resource or books that explains such better. I'm not new to Android but this definitely is.
Assigning a reference won't copy an object. It is not related to EditText
Upvotes: 8