TimerTask nach Neustart

Wir sammeln alle Infos der Bonusepisode von Pokémon Karmesin und Purpur für euch!

Zu der Infoseite von „Die Mo-Mo-Manie“
  • Hallo Leute!


    Ich schreibe schon seit einigen Monaten an einem Widget und habe schon seit Anfang an einen merkwürdigen Fehler den ich sonst nirgendwo antreffen konnte.


    Die Situation ist folgende:


    Mein Widget startet nach dem Bootvorgang einen TimerTask der eine Updateroutine im ausgelesenen Intervall aufruft.
    Allerdings wird der Timer immer nur ein einziges mal ausgeführt. Ich bekomme also genau ein Update und dann nie wieder eines.
    Die Run()-Funktion des TimerTasks wird nicht mehr aufgerufen, als sei das Intervall vollkommen ignoriert worden.


    Kurioserweise tritt der Fehler nur in dieser Situation auf, nutze ich ganz normal OnUpdate() und lege das Widget im laufenden Betrieb auf den Homescreen funktioniert der Timer.
    Auch wenn ich manuell nach dem Bootvorgang einen Intent sende wird der Timer ordnungsgemäß gestartet.


    Der Fehler tritt wirklich nur auf wenn das Widget bereits auf dem Homescreen liegt und ich das Gerät neu starte.
    Ich entwickle das Widget in Android Studio und der Fehler tritt auf einem virtuellen Testgerät nicht auf.


    Ein paar Codeauszüge:


    Java
    @Override    public void onReceive(Context in_context, Intent in_intent) {        if(Intent.ACTION_BOOT_COMPLETED.equals(in_intent.getAction())) {            context = in_context;            startTimer();        }    }
    Java
    public void startTimer() {        killTime(); // Entferne laufende Timer        SharedPreferences pref = context.getSharedPreferences("preferences", 0); // Verweis zu den SharedPreferences        int value0 = Integer.parseInt(pref.getString("v0", "0"));   // Lese den Wert 0 (das Updateintervall) aus        switch(value0) {            case 0: updateInterval = 60000;  // Update jede Minute                break;            case 1: updateInterval = 300000; // Update alle 5 Minuten                break;            case 2: updateInterval = 600000; // Update alle 10 Minuten                break;            case 3: updateInterval = 1800000; // Update alle 30 Minuten                break;            default: updateInterval = 60000;  // Update sonst auch jede Minute        }        timer = new Timer();        timer.scheduleAtFixedRate(new tTask(), 0, updateInterval); // Starte alle (x) Minuten ein Update    }
    Java
    private class tTask extends TimerTask { // Timer, der in regelmäßigen Abständen updatet
            public void run() {
                context.startService(new Intent(context, UpdateWidget.class)); // Starte die Update-Routine
            }
        }


    Hilfe wäre echt nett, ich hatte nie ne wirkliche Einführung in Android und Java, deswegen vermute ich mal das der Fehler total lächerlich ist :S


    PS: An den TimerTasks selbst scheints nicht zu liegen, mit Handlern tritt das gleiche Problem auf.

  • Klingt für mich ganz danach, als würde dein Timer irgendwann zwischendurch vom Garbage Collector gefressen, weil dein Programm nirgends mehr Referenzen darauf hat (beziehungsweise auf die Objekte, die Referenzen auf ihn haben und so weiter).

    FC (PKMN Y): 3282-3144-2343 — Safarityp: Pflanze (Maracamba, Folikon, Tangela) — Bei Interesse schickt mir einfach ne PM ;)


    Testet meine Pokemon-Checkliste für Gen. 1 bis 6 (für Sammler, und solche die es werden wollen – jetzt mit vollständiger Habitatsliste für alle Editionen – OR/AS noch minimal unvollständig)

  • Klingt für mich ganz danach, als würde dein Timer irgendwann zwischendurch vom Garbage Collector gefressen, weil dein Programm nirgends mehr Referenzen darauf hat (beziehungsweise auf die Objekte, die Referenzen auf ihn haben und so weiter).

    Ein Timer wird nicht collected, solange er noch Tasks gescheduled hat. Zitat aus der Dokumentation:


    Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially. [...]


    After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection).

    Auch wenn im Usercode selbst keine Referenzen mehr auf das Timer-Objekt existieren, wird es also nicht collected, solange es noch Tasks dafür gibt. Und einen Task hat -GetaX- ja gescheduled. Das kanns also nicht sein.


    Was jetzt wirklich die Ursache sein könnte, weiß ich aber leider auch nicht.

  • Klingt für mich ganz danach, als würde dein Timer irgendwann zwischendurch vom Garbage Collector gefressen, weil dein Programm nirgends mehr Referenzen darauf hat (beziehungsweise auf die Objekte, die Referenzen auf ihn haben und so weiter).

    Kann ich mir eigentlich nicht vorstellen, dann müsste das ja auch immer so sein und nicht nur beim ersten mal.


    Habe übrigens nen Fix der ziemlich blöd aussieht ... aber es läuft.
    Ich sende jetzt einfach bei BOOT_COMPLETED einen neuen Intent an sich selbst. Und der geht, keine Ahnung wieso ._.


    Die TimerTasks hab ich übrigens durch Handler ersetzt, man sagte mir das wäre eleganter.