7

In the source code of Activity.java, I see some methods bellow :

public View findViewById(int id) {
    return getWindow().findViewById(id);
}

and the definition of getWindow method:

public Window getWindow() {
    return mWindow;
}

But as the following rules:

Avoid Internal Getters/Setters

In native languages like C++ it's common practice to use getters (e.g. i = getCount()) instead of accessing the field directly (i = mCount). This is an excellent habit for C++, because the compiler can usually inline the access, and if you need to restrict or debug field access you can add the code at any time.

On Android, this is a bad idea. Virtual method calls are expensive, much more so than instance field lookups. It's reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.

Without a JIT, direct field access is about 3x faster than invoking a trivial getter. With the JIT (where direct field access is as cheap as accessing a local), direct field access is about 7x faster than invoking a trivial getter. This is true in Froyo, but will improve in the future when the JIT inlines getter methods.

so I want to know why android developers not access this mWindow object directly? If the JIT of the current android versions cannot inline the access, getWindow().findViewById(id) will costs more time than mWindow.findViewById(id), and findViewById is a rather frequently used method.

teoking
  • 127
  • 7

3 Answers3

2

First: you can't access it because it's private.

Why is it private?

As you said, accessing members directly is faster. On the other hand, you are invoking a method that isn't very fast as it will lookup for some view in the view hierarchy. So using a method instead of a direct access will incur in a small overhead in terms of percentage of the total time that it would take to perform that task.

Anyway, I believe that the reason for this is encapsulation.

You are invoking something you don't own (that is the Android SDK). So, you shouldn't make any assumptions of whats happening "in the other side". Simply use this method and expect that it will return the view you want (or null if it doesn't exists).

Maybe the next version of android will use a different method to lookup a view, not calling getWindow(). If you use this method, they (Google/Android) can simply mark the method as deprecated and "forward" your invocation to the newest implementation. If you were calling directly getWindow(), maybe you would be looking for something that is no longer placed in there.

Pedro Loureiro
  • 11,436
  • 2
  • 31
  • 37
  • I don't need to call getWindow() all the time to assess the view members. Nonetheless, we are customers for android apis, I wanna to know why they wrote the code like that, why not this, it's something worth that I care. And thank you for your answer. – teoking Dec 29 '10 at 08:55
  • You didn't understand me right. In gigerbread, findView might use information stored somewhere in the window object. Honeycomb google might decide to change the view hierarchy system and store the corresponding information in another place, with another format using other data structures. If you use directly window, it won't work in the new version. If you use findView, google can invoke the new implementation. More info: http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming) – Pedro Loureiro Dec 29 '10 at 13:11
  • my last link should be http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming%29 – Pedro Loureiro Dec 29 '10 at 14:40
1

You can't access the mWindow property directly - it's private. And I wouldn't care about the speed of findViewById, since you only need to call it once for every view in your layout in your onCreate() method and store the views in members of your activity. You do call findViewById only once per view, don't you? ;-)

However, if you really care about these things, you could call getWindow() for yourself, store it into a local variable and call findViewById on it directly. I wouldn't recommend this because all your performance increasements here are not worth the time and anyway will be obsolete with future versions of the JIT.

If you do this I would be very interested in the amount of microseconds you saved. :-)

mreichelt
  • 12,359
  • 6
  • 56
  • 70
  • Thanks for you answer. I certainly call findViewById once for each view as you said. Maybe I misunderstood the principle, and now it's clear. – teoking Dec 29 '10 at 08:48
0

We have a reason to smile now...

The android documentation which says to avoid internal getters and setters will change soon, supposedly progruard was added to Gingerbread platform which does a fine job of inlining accessor's, please refer to "Avoid Internal Getters/Setters" is bad advice and these two SO posts.

  1. https://stackoverflow.com/a/6716573/892055

  2. https://stackoverflow.com/a/4930538/892055

Community
  • 1
  • 1
Arif Nadeem
  • 8,524
  • 7
  • 47
  • 78