0

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....

tom91136
  • 8,662
  • 12
  • 58
  • 74
  • It is possible that they used to use an anonymous inner class or something in here that dictated the use of `final`, changed the code to get rid of that anonymous inner class, and simply didn't get rid of the `final`. "Is this a design pattern?" -- not that I am aware of. – CommonsWare Aug 16 '14 at 12:40
  • @CommonsWare if they had an anonymous inner class they wouldnt still need final. they could access the mAttachInfo still. – eldjon Aug 16 '14 at 14:06
  • @eldjon: They would if they wanted the anonymous inner class instance to refer to the *current* value of `mAttachInfo`, rather than the value of `mAttachInfo` that existed at the time the instance of the anonymous inner class was used. Again, though, that was just a guess. – CommonsWare Aug 16 '14 at 14:07
  • I've checked earlier versions of the API and made an edit – tom91136 Aug 18 '14 at 10:03

1 Answers1

1

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.

akwizgran
  • 176
  • 1
  • 8