Jest zatem kilka rzeczy do rozważenia, ponieważ istnieje tak wiele sposobów na skórowanie tego kota. Chociaż wszystkie odpowiedzi zostały już wybrane i wybrane. Myślę, że ważne jest, aby ponownie zapoznać się z odpowiednimi wytycznymi dotyczącymi kodowania, aby uniknąć sytuacji, w której ktoś pójdzie w niewłaściwym kierunku tylko z powodu „większości wybranych prostych odpowiedzi”.
Więc najpierw omówmy prostą odpowiedź Post Delayed, która jest ogólnie wybraną odpowiedzią w tym wątku.
Kilka rzeczy do rozważenia. Po opóźnieniu postu możesz napotkać wycieki pamięci, martwe przedmioty, cykle życia, które zniknęły i wiele więcej. Ważne jest więc również odpowiednie obchodzenie się z nim. Możesz to zrobić na kilka sposobów.
Ze względu na nowoczesny rozwój dostarczę w KOTLIN
Oto prosty przykład użycia wątku interfejsu użytkownika na wywołaniu zwrotnym i potwierdzeniu, że Twoja aktywność nadal działa i ma się dobrze po uderzeniu w wywołanie zwrotne.
Handler(Looper.getMainLooper()).postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
Jednak nadal nie jest to idealne, ponieważ nie ma powodu, aby oddzwonić, jeśli aktywność zniknęła. więc lepszym sposobem byłoby zachować odniesienie do niego i usunąć jego wywołania zwrotne w ten sposób.
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)
}
}
i oczywiście zajmuj się czyszczeniem w onPause, aby nie oddzwoniło.
override fun onPause() {
super.onPause()
mHandler.removeCallbacks(null)
}
Teraz, kiedy omawialiśmy to, co oczywiste, porozmawiajmy o czystszej opcji z nowoczesnymi coroutines i kotlin :). Jeśli jeszcze ich nie używasz, naprawdę brakuje.
fun doActionAfterDelay()
launch(UI) {
delay(MS_TO_DELAY)
actionToTake()
}
}
lub jeśli chcesz zawsze uruchamiać interfejs użytkownika dla tej metody, możesz po prostu zrobić:
fun doActionAfterDelay() = launch(UI){
delay(MS_TO_DELAY)
actionToTake()
}
Oczywiście, podobnie jak PostDelayed, musisz upewnić się, że poradzisz sobie z anulowaniem, więc możesz albo sprawdzić aktywność po opóźnionym połączeniu, albo możesz anulować go w onPause, tak jak na innej trasie.
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}")
}
}
}
}
// obsługa czyszczenia
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
}
}
Jeśli umieścisz uruchomienie (UI) w podpisie metody, zadanie może zostać przypisane w linii wywołującej kodu.
więc morał tej historii jest bezpieczny przy opóźnionych działaniach, upewnij się, że usunąłeś oddzwanianie lub anulowałeś swoje zadania i oczywiście potwierdziłeś, że masz odpowiedni cykl życia, aby dotknąć elementów opóźnionego oddzwaniania. Coroutines oferuje także akcje, które można anulować.
Warto również zauważyć, że zwykle powinieneś sobie poradzić z różnymi wyjątkami, które mogą pochodzić z coroutines. Na przykład anulowanie, wyjątek, limit czasu, cokolwiek zdecydujesz się użyć. Oto bardziej zaawansowany przykład, jeśli zdecydujesz się naprawdę zacząć używać 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}")
}
}