Es gibt also ein paar Dinge zu beachten, da es so viele Möglichkeiten gibt, diese Katze zu häuten. Obwohl alle Antworten bereits ausgewählt und ausgewählt wurden. Ich denke, es ist wichtig, dass dies mit den richtigen Codierungsrichtlinien überprüft wird, um zu vermeiden, dass jemand in die falsche Richtung geht, nur weil "die Mehrheit die einfache Antwort ausgewählt hat".
Lassen Sie uns zunächst die einfache Antwort "Post Delayed" diskutieren, bei der es sich insgesamt um die vom Gewinner ausgewählte Antwort in diesem Thread handelt.
Ein paar Dinge zu beachten. Nach der Nachverzögerung können Speicherlecks, tote Objekte, verschwundene Lebenszyklen und mehr auftreten. Daher ist es auch wichtig, richtig damit umzugehen. Sie können dies auf verschiedene Arten tun.
Für die moderne Entwicklung werde ich in KOTLIN liefern
Hier ist ein einfaches Beispiel für die Verwendung des UI-Threads bei einem Rückruf und die Bestätigung, dass Ihre Aktivität 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)
Dies ist jedoch immer noch nicht perfekt, da es keinen Grund gibt, Ihren Rückruf zu tätigen, wenn die Aktivität abgebrochen wurde. Ein besserer Weg wäre es, einen Verweis darauf zu behalten und die Rückrufe wie diesen zu entfernen.
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 die Bereinigung in der onPause durchführen, damit der Rückruf nicht getroffen wird.
override fun onPause() {
super.onPause()
mHandler.removeCallbacks(null)
}
Nachdem wir das Offensichtliche besprochen haben, sprechen wir über eine sauberere Option mit modernen Coroutinen und Kotlin :). Wenn Sie diese noch nicht verwenden, verpassen Sie sie wirklich.
fun doActionAfterDelay()
launch(UI) {
delay(MS_TO_DELAY)
actionToTake()
}
}
oder wenn Sie mit dieser Methode immer einen UI-Start durchführen möchten, können Sie einfach Folgendes tun:
fun doActionAfterDelay() = launch(UI){
delay(MS_TO_DELAY)
actionToTake()
}
Natürlich müssen Sie genau wie beim PostDelayed sicherstellen, dass Sie mit dem Abbrechen umgehen, damit Sie entweder die Aktivitätsprüfungen nach dem Verspätungsaufruf durchführen oder sie in der onPause wie auf der anderen 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}")
}
}
}
}
// Bereinigung behandeln
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 den Start (UI) in die Methodensignatur einfügen, kann der Job in der aufrufenden Codezeile zugewiesen werden.
Die Moral der Geschichte ist es also, mit Ihren verspäteten Aktionen sicher zu sein, sicherzustellen, dass Sie Ihre Rückrufe entfernen oder Ihre Jobs stornieren, und natürlich zu bestätigen, dass Sie den richtigen Lebenszyklus haben, um Elemente Ihres verspäteten Rückrufs vollständig zu berühren. Die Coroutinen bieten auch stornierbare Aktionen an.
Es ist auch erwähnenswert, dass Sie normalerweise die verschiedenen Ausnahmen behandeln sollten, die mit Coroutinen einhergehen können. Zum Beispiel eine Stornierung, eine Ausnahme, eine Zeitüberschreitung, was auch immer Sie verwenden möchten. Hier ist ein fortgeschritteneres Beispiel, wenn Sie sich entscheiden, Coroutinen 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}")
}
}