Reputation: 8962
Sorry I can't come up with a better question title because it's pretty hard to describe...
I was inspecting Android's source (4.4 KK), the View
class in particular and this showed up:
// .... lots of stuff....
AttachInfo mAttachInfo;
// .... lots of stuff....
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
That's the View.post(Runnable)
that we all love to use whenever we need something to run on the UI thread.
The thing I don't understand here is why do they create another local reference of attachInfo
?
Why don't they do it like:
if (mAttachInfo != null) {
return mAttachInfo.mHandler.post(action);
}
Other than making attachInfo
immutable in the method scope to prevent bugs(even thought they can still accidentally access mAttachInfo
), I don't think there's any reason to do this.
Another possibility would be to shorten names, but I don't think it's worth shorting 1 character.
Is this a design pattern?
EDIT: further inspecting the source reveals that they use this "pattern" in many places:
public void postInvalidateOnAnimation() {
// We try only with the AttachInfo because there's no point in invalidating
// if we are not attached to our window
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
}
}
Basically, they use it in almost every postXXXXXX()
method.
EDIT2:
@CommonsWare pointed out that it might be used for anonymous inner class in previous versions, I checked the source of 1.5(Cupcake) ~ 2.3.3(Gingerbread) and this is what post(
) looks like
public boolean post(Runnable action) {
Handler handler;
if (mAttachInfo != null) {
handler = mAttachInfo.mHandler;
} else {
// Assume that post will succeed later
ViewRoot.getRunQueue().post(action);
return true;
}
return handler.post(action);
}
I still don't see why....
Upvotes: 0
Views: 1254
Reputation: 176
Bear in mind that post()
may be called from background threads at the same time as mAttachInfo
is updated on the UI thread. The code that was used up to Android 2.3.3 could throw an NPE if mAttachInfo
was set to null after the if (mAttachInfo != null)
check and before mAttachInfo.mHandler
was accessed.
The current code avoids the NPE by taking a snapshot of mAttachInfo
that doesn't change for the lifetime of the method.
The local variable doesn't strictly need to be final, but declaring it final makes it extra clear that it won't become null after the if (attachInfo != null)
check.
Upvotes: 1