Vì vậy, có một vài điều cần xem xét ở đây vì có rất nhiều cách để lột da con mèo này. Mặc dù câu trả lời đã được đưa ra và lựa chọn. Tôi nghĩ điều quan trọng là điều này phải được xem xét lại với các hướng dẫn mã hóa phù hợp để tránh bất kỳ ai đi sai hướng chỉ vì "câu trả lời đơn giản được chọn đa số".
Vì vậy, trước tiên hãy thảo luận về câu trả lời bị trì hoãn bài đơn giản là câu trả lời được lựa chọn chung cho chủ đề này.
Một vài điều cần xem xét. Sau khi trì hoãn bài đăng, bạn có thể gặp phải rò rỉ bộ nhớ, các vật thể chết, vòng đời đã biến mất và hơn thế nữa. Vì vậy, xử lý nó đúng cách cũng quan trọng. Bạn có thể làm điều này theo một vài cách.
Vì lợi ích của sự phát triển hiện đại, tôi sẽ cung cấp trong KOTLINE
Dưới đây là một ví dụ đơn giản về việc sử dụng chuỗi UI trên một cuộc gọi lại và xác nhận rằng hoạt động của bạn vẫn còn sống và tốt khi bạn nhấn vào cuộc gọi lại của mình.
Handler(Looper.getMainLooper()).postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
Tuy nhiên, điều này vẫn chưa hoàn hảo vì không có lý do gì để đánh lại cuộc gọi lại của bạn nếu hoạt động đã biến mất. Vì vậy, một cách tốt hơn sẽ là giữ một tham chiếu đến nó và loại bỏ các cuộc gọi lại như thế này.
private fun showFacebookStylePlus1NewsFeedOnPushReceived(){
A35Log.v(TAG, "showFacebookStylePlus1NewsFeedOnPushReceived")
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.VISIBLE
mHandler.postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
}
}
và tất nhiên xử lý dọn dẹp trên onPause để nó không bị gọi lại.
override fun onPause() {
super.onPause()
mHandler.removeCallbacks(null)
}
Bây giờ chúng ta đã nói chuyện rõ ràng, hãy nói về một lựa chọn sạch hơn với coroutines và kotlin hiện đại :). Nếu bạn chưa sử dụng những thứ này, bạn thực sự đang bỏ lỡ.
fun doActionAfterDelay()
launch(UI) {
delay(MS_TO_DELAY)
actionToTake()
}
}
hoặc nếu bạn muốn luôn luôn khởi chạy UI trên phương thức đó, bạn chỉ cần làm:
fun doActionAfterDelay() = launch(UI){
delay(MS_TO_DELAY)
actionToTake()
}
Tất nhiên, giống như PostDelayed, bạn phải đảm bảo rằng bạn xử lý việc hủy để bạn có thể thực hiện kiểm tra hoạt động sau cuộc gọi trì hoãn hoặc bạn có thể hủy nó trong onPause giống như tuyến khác.
var mDelayedJob: Job? = null
fun doActionAfterDelay()
mDelayedJob = launch(UI) {
try {
delay(MS_TO_DELAY)
actionToTake()
}catch(ex: JobCancellationException){
showFancyToast("Delayed Job canceled", true, FancyToast.ERROR, "Delayed Job canceled: ${ex.message}")
}
}
}
}
// xử lý dọn dẹp
override fun onPause() {
super.onPause()
if(mDelayedJob != null && mDelayedJob!!.isActive) {
A35Log.v(mClassTag, "canceling delayed job")
mDelayedJob?.cancel() //this should throw CancelationException in coroutine, you can catch and handle appropriately
}
}
Nếu bạn đặt khởi chạy (UI) vào chữ ký phương thức, công việc có thể được chỉ định trong dòng gọi mã.
Vì vậy, đạo đức của câu chuyện là an toàn với các hành động bị trì hoãn của bạn, đảm bảo bạn xóa các cuộc gọi lại hoặc hủy công việc của mình và tất nhiên xác nhận rằng bạn có vòng đời phù hợp để chạm vào các mục trong quá trình gọi lại chậm trễ của bạn. Các Coroutines cũng cung cấp các hành động hủy bỏ.
Cũng đáng lưu ý rằng bạn thường nên xử lý các ngoại lệ khác nhau có thể đi kèm với coroutines. Ví dụ: hủy bỏ, ngoại lệ, hết thời gian, bất cứ điều gì bạn quyết định sử dụng. Dưới đây là một ví dụ nâng cao hơn nếu bạn quyết định thực sự bắt đầu sử dụng coroutines.
mLoadJob = launch(UI){
try {
//Applies timeout
withTimeout(4000) {
//Moves to background thread
withContext(DefaultDispatcher) {
mDeviceModelList.addArrayList(SSDBHelper.getAllDevices())
}
}
//Continues after async with context above
showFancyToast("Loading complete", true, FancyToast.SUCCESS)
}catch(ex: JobCancellationException){
showFancyToast("Save canceled", true, FancyToast.ERROR, "Save canceled: ${ex.message}")
}catch (ex: TimeoutCancellationException) {
showFancyToast("Timed out saving, please try again or press back", true, FancyToast.ERROR, "Timed out saving to database: ${ex.message}")
}catch(ex: Exception){
showFancyToast("Error saving to database, please try again or press back", true, FancyToast.ERROR, "Error saving to database: ${ex.message}")
}
}