Read the original article:How to Resolve the Issue of TextTimer Failing to Time
Problem Description
TextTimer displays timing information through text and controls its timer status, enabling flexible implementation of scenarios such as countdowns and sports timing. When using the TextTimer component to achieve these functions, it is common to encounter situations where timing cannot be performed.
Background Knowledge
TextTimer is a component that displays timing information through text and controls its timer status. It is often used in mobile verification code scenarios. After obtaining the verification code, it starts a countdown to determine the validity of the verification code.
The page lifecycle, i.e., the lifecycle of the component decorated with @Entry, triggers the aboutToAppear, onPageShow, and other lifecycle interfaces in sequence when the page is created. At this point, the page object has been created, but the component elements within the page may not have been created.
Timer provides basic timer capabilities and supports executing corresponding functions at specified times.
HarmonyOS has a background operation management mechanism. When an app is in the background for a period of time, the app process will be suspended. After suspension, the app process cannot use software resources (such as public events and timers) and hardware resources (such as CPU, network, GPS, Bluetooth, etc.). If an app wants to perform tasks in the background, it must apply for the corresponding permissions.
When a TextTimer fails to time properly, it's usually due to errors in state management, lifecycle, or configuration. The following are common symptoms:
| Problem Phenomenon | Cause Of The Problem |
|---|---|
| Timer not started after page displayed | onPageShow is the callback when the page is displayed. At this time, the TextTimer may not be created. |
| The app background countdown is invalid | TextTimer will time normally, but the time change in the background state will not trigger onTimer |
Solution
Page loading is an asynchronous process. The page object is created first, followed by the loading of internal component elements. Depending on the complexity of the page, the TextTimer object may not be created when the onPageShow lifecycle function is triggered. There are two scenarios as follows:
- Simple page with fewer elements in the component tree and shallow hierarchy: Column->TextTimer. The TextTimer object is already created during the onPageShow lifecycle of the page, and the timer starts successfully.
- Complex page with deep hierarchy in the component tree: Column->List->ListItem->TextTimer. The TextTimer object is not yet created during the onPageShow lifecycle of the page, and the timer fails to start.
When the application is in the foreground, changes in the TextTimer countdown will trigger the onTimer callback. However, this event will not be triggered when the device is locked or the application is in the background. To address this, use a setTimeout timer instead of the onTimer event and request background task permissions.
Solution 1:
1.Do not start the timer in the onPageShow of the page. Start it after the TextTimer is mounted to the component tree and displayed. That is, bind the start of the timer to its own lifecycle onAppear. For detailed examples, please refer to Execute timing immediately after creation. The key code is as follows:
TextTimer({ isCountDown: true, count: 30000, controller: this.textTimerController })
.onAppear(() => {
this.textTimerController.start()
})
2.Configure the backgroundModes permission in the module.json5 file. When the TextTimer timer starts, set the timer setTimeout to replace the TextTimer onTimer event to implement the countdown end processing operation when the app is in the background.
"module": {
"abilities": [
{
"backgroundModes": ["taskKeeping"] // Configured as required
}
]
}
TextTimer({ isCountDown: true, count: 30000, controller: this.textTimerController })
.onAppear(() => {
this.textTimerController.start() // Launch Text Timer
setTimeout(() => {
// Execute the operation after the 30-second countdown ends.
}, 30000) // Align with the time set by TextTimer
})
// This onTimer does not trigger when in the background.
.onTimer((utc: number, elapsedTime: number) => {
// ...
})
Solution 2: Use onAttach
@Entry
@Component
struct TextTimerExample {
textTimerController: TextTimerController = new TextTimerController()
@State format: string = 'mm:ss.SS'
build() {
Column() {
TextTimer({ isCountDown: true, count: 30000, controller: this.textTimerController })
.format(this.format)
.fontColor(Color.Black)
.fontSize(50)
.onTimer((utc: number, elapsedTime: number) => {
console.info('textTimer notCountDown utc is:' + utc + ', elapsedTime: ' + elapsedTime)
})
.onAttach(() => {
this.textTimerController.start()
})
}
}
}
Solution 3: Use onVisibleAreaChange
@Entry
@Component
struct TextTimerExample {
textTimerController: TextTimerController = new TextTimerController()
@State format: string = 'mm:ss.SS'
build() {
Column() {
TextTimer({ isCountDown: true, count: 30000, controller: this.textTimerController })
.format(this.format)
.fontColor(Color.Black)
.fontSize(50)
.onTimer((utc: number, elapsedTime: number) => {
console.info('textTimer notCountDown utc is:' + utc + ', elapsedTime: ' + elapsedTime)
})
.onVisibleAreaChange([0.0, 1.0], (isExpanding: boolean, currentRatio: number) => {
this.textTimerController.start()
})
}
}
}
Verification Result

This sample supports API version 20 Release and later.
This sample supports HarmonyOS 6.0.0 Release SDK and later.
This sample must be built and run using DevEco Studio 6.0.0 Release or later.
Top comments (0)