I have done some Googling and searched in Android Developer website but I could not able to find a suitable answer. Can anyone help me out for this? thanks in advance.
- What they represent
- Waiting for views to exist/finding views
What they represent
In my words, UiObject2 is a direct representation of a real view that exists on the screen and allows you to take actions on that view. UiObject is a representation of how to find an element that may be on the screen, combined with actions that you can take on that view.
UiObject as the docs say, represents the method to find something on the screen. This means you can re-use a UiObject instance to find another instance of a matching element at a later time.
For example: you can find a toolbar on one screen using the UiObject api (UiDevice.findObject(UiSelector)) to get an instance of UiObject, then open a modal dialog. Once the dialog is dismissed, you can then use the same instance to access the toolbar again.
UiObject2 as the docs say, represents a specific instance of an item on the page, and thus cannot be re-used to find another element at a later time in the same way that a UiObject can be. If you have a UiObject2 instance, you are “guarantee” that a view that matches that instance exists on the page, and the instance can only really be used once.
In the same example as above, after the modal dialog has been dismissed, you would have to use the UiObject2 api (UiDevice.findObject(Until….)) to retrieve a new instance of a UiObject2 that represents the toolbar, because the old one has gone stale by that point.
Waiting for views to exist/finding views
You will likely want to wait for a view to exist on the page after you take an action. There are two ways of doing this:
- UiDevice.findObject(UiSelector) (returns UiObject) followed by UiObject.waitForExists(timeout)
- UiDevice.wait(Until.findObject(SearchCondition), timeout)
In both cases, timeout is of type long
This is where the current api is a little inconsistent. In order to use method #2 above, you have to use the Until and By utility classes to describe how to find the view on the screen. Whereas for method #1 you only use the UiSelector methods.
You will find similar methods on the
By utility class as on the
UiSelector class, but the method names are quite different. For example By.res(String resourceName) accomplishes the same thing as UiSelector.resourceId(String id), but clearly have different names, that make you think they accomplish something different.
In my opinion: The UiObject api is nicer because locating a view is different than the operation to wait for a view. This allows you to wait for any view that you want to find, at any time. The UiObject2 api on the other hand, forces you to choose what to do: you either call
device.findObject(By...) or you call
device.wait(Until.findObject(By...)), but you’re forced to make the choice of whether to wait or not ahead of time.
A UiObject2 has one “bare bones” scrolling method: UiObject2.scroll(Direction, percentage). This method allows you to scroll in a particular direction with a pre-specified amount of scrolling, but definitely isn’t very convenient, as the user has to decide how much to scroll. I can see this method being put into a loop of: scroll, check if element is visible, repeat.
UiScrollable on the other hand has methods that are much more convenient for scrolling: UiScrollable.scrollIntoView(…) for example. This method takes a UiSelector and appears to “do what must be done” to get a match on that UiSelector and to make that visible. This is much more useful than UiObject2, as the api takes care of everything for you, and no loops are required.
To get an instance of UiObject, you must use a method on UiDevice like
UiDevice.findObject(UiSelector). You used to be able to instantiate a UiObject directly, but that constructor was deprecated in February, 2014 because it hid the fact that it was using UiDevice to find the element.
UiScrollable is a subclass of UiObject. A UiScrollable has one constructor that takes a UiSelector as an argument. This constructor simply calls super until it gets to the deprecated constructor of UiObject mentioned above.
To reiterate: you can only get a UiObject by using UiDevice. But to get a UiScrollable, you can only instantiate it directly, using the constructor that has been labled as deprecated.
Opinion: Semantic Naming
In my opinion: if UiObject2 was named something like
ResolvedUiObject or something, it would make the api intentions clearer. UiObject2 doesn’t communicate the semantic purpose of the class, and therefore leads to this stackoverflow question.
I would almost go as far as saying that
UiObject.waitForExists() should return UiObject2 as it is written, because UiObject’s is used essentially as a locator (though I guess, that’s what UiSelctor is :/) for a view combined with actions to take on the view, and UiObject2 contains methods for just taking actions on the view.
A UiObject is a representation of a view.
It is not in any way directly bound to a view as an object reference.
A UiObject contains information to help it locate a matching view at runtime
based on the UiSelector properties specified in its constructor.
Once you create an instance of a UiObject, it can be reused for different
views that match the selector criteria.
A UiObject2 represents a UI element. Unlike UiObject, it is bound to a
particular view instance and can become stale if the underlying view object is destroyed.
As a result, it may be necessary to call findObject(BySelector) to obtain a
new UiObject2 instance if the UI changes significantly.