Wait Conditions¶
The wait engine lets you pause execution until a condition is met. Built-in conditions cover common scenarios, and combinators let you compose them.
Basic Usage¶
from adbflow.wait import wait_for, TextVisible, ActivityIs, ScreenOn
async def wait_examples(device):
# Wait for text to appear on screen
await wait_for(
TextVisible(device, "Welcome"),
timeout=10.0
)
# Wait for a specific activity
await wait_for(
ActivityIs(device, "com.example.app/.MainActivity"),
timeout=10.0
)
# Wait for screen to turn on
await wait_for(ScreenOn(device), timeout=5.0)
If the condition isn't met within the timeout, WaitTimeoutError is raised.
Built-in Conditions¶
| Condition | True when... |
|---|---|
TextVisible |
Text appears in the UI hierarchy dump |
ActivityIs |
Foreground activity matches the given name |
ScreenOn |
Device screen is on |
ScreenOff |
Device screen is off |
PackageRunning |
A package has a running process |
ElementExists |
A custom async match function returns True |
ElementExists¶
Use ElementExists for custom conditions:
from adbflow.wait import wait_for, ElementExists
async def custom_condition(device):
# Wait until a specific element is found
async def check():
element = await device.ui.find_async(
Selector().resource_id("com.example:id/loaded")
)
return element is not None
await wait_for(ElementExists(check), timeout=10.0)
Combinators¶
Compose conditions with AnyOf, AllOf, and Not:
from adbflow.wait import wait_for, TextVisible, ScreenOn, any_of, all_of, not_
async def combinator_examples(device):
# Wait for ANY condition to be true
await wait_for(
any_of(
TextVisible(device, "Success"),
TextVisible(device, "Error"),
),
timeout=10.0
)
# Wait for ALL conditions to be true
await wait_for(
all_of(
ScreenOn(device),
TextVisible(device, "Ready"),
),
timeout=10.0
)
# Negate a condition
await wait_for(
not_(TextVisible(device, "Loading...")),
timeout=15.0
)
# Complex combinations
await wait_for(
all_of(
ScreenOn(device),
any_of(
TextVisible(device, "Home"),
TextVisible(device, "Dashboard"),
),
),
timeout=10.0
)
Device Shortcut Methods¶
The Device object has convenience methods for common waits:
async def device_shortcuts(device):
# Wait for text
found = await device.wait_for_text_async("Welcome", timeout=10.0)
# Wait for activity
found = await device.wait_for_activity_async(
"com.example.app/.MainActivity",
timeout=10.0
)
Polling Interval¶
The interval parameter controls how often the condition is checked:
# Check every 200ms (faster but more CPU)
await wait_for(TextVisible(device, "Done"), timeout=10.0, interval=0.2)
# Check every 2 seconds (slower but lighter)
await wait_for(TextVisible(device, "Done"), timeout=30.0, interval=2.0)
The default interval is 0.5 seconds.
Tips¶
- Use
any_ofwhen waiting for one of several possible outcomes (e.g., success or error dialog). - Use
all_ofwhen multiple conditions must hold simultaneously. - Use
not_to wait for something to disappear (e.g., a loading spinner). - Keep timeouts reasonable — a 60-second wait is usually a sign something is wrong.