Hier gibt es also einiges zu beachten, denn es gibt so viele Möglichkeiten, diese Katze zu häuten. Obwohl alle Antworten bereits ausgewählt und ausgewählt worden sind. Ich denke, es ist wichtig, dass dies mit angemessenen Kodierungsrichtlinien überarbeitet wird, um zu vermeiden, dass irgendjemand in die falsche Richtung geht, nur weil die "Mehrheit eine einfache Antwort ausgewählt hat".
Lassen Sie uns also zunächst die einfache Antwort "Post Delayed" besprechen, die in diesem Thread als beste Antwort ausgewählt wurde.
Es gibt einige Dinge zu beachten. Nach der Post-Delay-Phase kann es zu Speicherlecks, toten Objekten, nicht mehr vorhandenen Lebenszyklen und vielem mehr kommen. Daher ist es wichtig, auch damit richtig umzugehen. Dazu gibt es mehrere Möglichkeiten.
Der modernen Entwicklung zuliebe werde ich in KOTLIN liefern
Hier ist ein einfaches Beispiel für die Verwendung des UI-Threads für einen Rückruf und die Bestätigung, dass Ihre Aktivität immer noch aktiv ist, wenn Sie Ihren Rückruf ausführen.
Handler(Looper.getMainLooper()).postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
Allerdings ist dies immer noch nicht perfekt, da es keinen Grund gibt, Ihre Callback zu treffen, wenn die Aktivität weg gegangen ist. so ein besserer Weg wäre, einen Verweis auf sie zu halten und entfernen Sie es Callbacks wie diese.
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)
}
}
und natürlich Cleanup auf der onPause, so dass es nicht den Rückruf getroffen.
override fun onPause() {
super.onPause()
mHandler.removeCallbacks(null)
}
Nachdem wir nun das Offensichtliche besprochen haben, lassen Sie uns über eine sauberere Option mit modernen Coroutines und Kotlin sprechen :). Wenn Sie diese noch nicht verwenden, verpassen Sie wirklich etwas.
fun doActionAfterDelay()
launch(UI) {
delay(MS_TO_DELAY)
actionToTake()
}
}
oder wenn Sie immer einen UI-Start mit dieser Methode durchführen möchten, können Sie dies einfach tun:
fun doActionAfterDelay() = launch(UI){
delay(MS_TO_DELAY)
actionToTake()
}
Natürlich müssen Sie genau wie bei PostDelayed sicherstellen, dass Sie das Abbrechen handhaben, so dass Sie entweder die Aktivitätsprüfungen nach dem Verzögerungsaufruf durchführen können oder es in der onPause genau wie die andere Route abbrechen können.
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}")
}
}
}
}
//Griffbereinigung
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
}
}
Wenn Sie launch(UI) in die Signatur der Methode aufnehmen, kann der Auftrag in der aufrufenden Codezeile zugewiesen werden.
Die Moral von der Geschichte ist also, dass Sie mit Ihren verzögerten Aktionen auf der sicheren Seite sein sollten. Stellen Sie sicher, dass Sie Ihre Rückrufe entfernen oder Ihre Aufträge abbrechen und natürlich sicherstellen, dass Sie den richtigen Lebenszyklus haben, um die Elemente auf Ihrem verzögerten Rückruf abzuschließen. Die Coroutines bietet auch abbrechbare Aktionen.
Es ist auch erwähnenswert, dass Sie normalerweise die verschiedenen Ausnahmen behandeln sollten, die mit Coroutines auftreten können. Zum Beispiel eine Annullierung, eine Ausnahme, eine Zeitüberschreitung, was auch immer Sie verwenden möchten. Hier ist ein fortgeschrittenes Beispiel, falls Sie sich entscheiden, Coroutines wirklich zu verwenden.
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}")
}
}