Beiträge von Adreoid

    Hallo,
    ich habe da ein merkwürdiges Problem mit dem FusedLocationProvider, welches ich mir nicht erklären kann.


    Ich starte in meiner Main Activity einen Service im Vordergrund durch einen Button-Klick mit:


    Code
    startLocationService ();



    Die Methode gehört zu einer Klasse "myLocationService" und sieht im Wesentlichen so aus:

    Das funktioniert auch so, die Methode locationCallback wird jetzt alle 5 Sekunden aufgerufen und ich bekomme die aktuelle Position..


    Jetzt habe ich die locationCallback-Methode erweitert.
    Im Prinzip möchte ich ein Ereignis auslösen, wenn ich Zuhause ankomme.


    Da es keinen Sinn macht, die aktuelle Position alle 5 Sekunden abzufragen, wenn ich noch sehr weit entfernt bin,
    wollte ich die Häufigkeit der Location Updates an die Restentfernung von Zuhause anpassen.


    Ich errechne bei jedem Aufruf der Callback die verbleibende Distanz zu einem festen Ziel (Zuhause) und versuche jetzt in der CallBack-Methode die Update Zeit zu verändern:




    Das Ergebnis sieht so aus:
    Die Location Updates kommen jetzt sehr schnell ( schneller als jede Sekunde)
    Hat jemand eine Idee, was da falsch sein könnte?


    Ich habe mal testweise beim Starten der Updates mit 5 Sekunden und beim Ändern auf 10 Minuten die Anzahl der Updates auf 1 gesetzt.



    Code
    locationRequest.setInterval        ( 10*60*1000 );
            locationRequest.setFastestInterval ( 10*60*1000 );
            locationRequest.setPriority        ( PRIORITY_HIGH_ACCURACY );
    
    
            locationRequest.setNumUpdates      ( 1 );

    Jetzt kommt nur noch das erste Update nach 5 Sekunden.


    Wenn ich da die Update Zeit auf 10 Minuten setze, kommen gar keine Updates mehr.

    Also ich habe das jetzt mal ausgiebig getestet.
    Die TCP/IP Kommandos (Tor auf, Tor zu) werden immer korrekt und vollständig gesendet.


    Wenn man nach Infos sucht, wie man einen Thread beendet, findet man nur Antworten, wie das von aussen geht (dort, wo er erzeugt und gestartet wird).
    Ich möchte allerdings, das sich der Thread selbst nach getaner Arbeit (senden eines einzelnen Kommandos) beendet und aus dem Speicher entfernt.
    Was wäre denn, wenn ich den in der Main-Activity erzeugten Thread einer Thread-Variablen zuweise?
    Würde er dann beendet und entfernt, wenn ich die Run-Methode mit return; verlasse?
    Oder geht das anders?
    Wie?

    Danke für deine Antwort.
    Das Ganze ist eine Torsteuerung für ein Carport (elektrisches Rolltor).
    Ich sende immer auf Buttonklick kurze TCP/IP Kommandos ( Tor hoch, Tor runter u.s.w.).
    Wenn die Verbindung nach dem Kommando wieder weg ist, macht das nichts, bzw ist das so gewollt.


    Wenn ich das richtig verstehe, wäre also der richtige Weg so:
    In der Run-Methode des Thread warten, bis das Kommando gesendet wurde und dann den Thread am Ende der Run Methode beenden?


    Merkwürdig nur:
    Der momentane Ablauf in der Run Methode ist ja so:
    Text senden
    Socket schließen.
    Run Methode beenden


    Wenn das Kommando noch nicht gesendet wurde, würde doch schon beim Schließen des Socket was schieflaufen?
    Tut es aber nicht.
    Also gehe ich mal davon aus, wenn ich den Socket schließe ist alles gesendet.


    Dann wäre nur die Frage: Wie den Thread am Ende der Run Methode beenden, damit er aus dem Speicher entfernt wird.

    Hallo,
    ich habe bisher wenig Java Erfahrung, und bin mir nicht sicher, ob ich nicht was falsch gemacht habe.


    Ich habe eine Main Activity mit einem onClickListener für einen Button.
    Wenn der Button geklickt wird, möchte ich ein kurzes Textkommando per TCP/IP versenden.
    Dazu erzeuge ich im onClickListener einen TcpSender - Thread, übergebe im "Konstruktor" den zu sendenden Text, und der Thread sendet den Text dann.
    Das funktioniert zwar scheinbar, aber ich bin nicht sicher, ob das so richtig programmiert ist.


    Zunächst mal die relevanten Code-Teile (nur das Wesentliche !!!)


    Ausschnitt aus der MainActivity:

    Code
    @Override
        public void onClick ( View v )
        {
        new Thread ( new com.bernd.demo.TcpSender( "HALLO" ) ).start ( );
        }


    Und hier Ausschnitte vom Sende-Thread:

    Jetzt meine Fragen:
    1. Im onClickListener erzeuge ich doch eigentlich bei jeden Button-Klick eine neue Instanz vom TcpSender-Thread.
    Müsste man den erzeugten Thread nicht einer Variablen zuweisen, und diese wieder zerstören? Wenn ja wo und wann?
    Oder erzeuge ich da einen riesigen Stapel von Threads und mülle meinen Speicher mit Thread-Leichen voll?


    2. Wie ist das mit der Run-Methode im Thread. Ich sende da was und dann?
    Wird die Run-Methode nach dem Senden beendet?
    Wenn sie beendet wird, ist dann auch das Thread-Objekt automatisch zerstört ? (das wäre die Antwort auf Frage 1)


    3. Könnte der Thread theoretisch schon zerstört werden, WÄHREND oder BEVOR die Daten komplett gesendet wurden?


    Vielen Dank im Voraus

    Hallo,
    ich plane gerade eine Erweiterung einer bestehenden App, und weiß nicht genau, welchen Weg ich dabei einschlagen soll
    (um am Ende festzustellen, dass er falsch war).


    Ich habe (vereinfacht) folgendes vor:
    Eine App hat u.a. einen Start und einen Stop Button.
    Klickt man Start, wird die aktuelle Position ermittelt und daraus eine Zeit abgeschätzt, die man mind. benötigt, um an einem festen Ziel (zuhause) anzukommen.


    Wenn ungefähr die halbe geschätzte Zeit abgelaufen ist, soll eine neue Positionsabfrage und eine neue Abschätzung der Restzeit bis zum Ziel erfolgen.
    Die nächste Abfrage dann wieder nach der halben geschätzten Restzeit u.s.w.


    Willkürliche Beispiele:
    Ist man bei Klick auf Start 100Km von zuhause entfernt dann könnten sich Positionsabfragen nach 30min, 22min, 15min , 8min, 3min, 2min, 1min ergeben.
    Ist man 200Km entfernt, dann nach 60min, 42min, 25min ........
    Oder anders ausgedrückt: Die Abfragen kommen umso häufiger, je näher man dem Ziel ist.


    Sobald die geschätzte Restzeit < 2min wird, soll eine Aktion ausgelöst werden (senden eines TCP/IP Kommandos an einen Server zuhause).


    Das Ganze soll auch noch funktionieren, wenn das Handy in den Standby geht, oder die App beendet wird,

    oder zum Beispiel wenn man heute startet, und erst übermorgen ankommt.
    Es sollte also im Hintergrund auch ohne die App laufen und möglichst nicht vom System rausgeworfen werden.
    Es gäbe da eine Menge Möglichkeiten:
    Service? Timer? Alarm?
    (welche Kombination läuft unabhängig im Hintergrund und wird nicht vom System beendet bzw. saugt mir nicht die Batterie leer?)
    Genügt jeweils die Last Known Position?
    (ich weiß nicht, wie aktuell die normalerweise ist. Eine Minute alt wäre ok, eine Stunde natürlich nicht.)


    Also meine Frage wäre:
    Mit welchen "Komponenten" (AlarmManager, Service, Thread, LastPosition .... ) Wie würde man das am besten realisieren?


    Vielen Dank

    Ich denke da an eine fehlende oder falsche Support Lib.
    Deshalb Gradle File

    Ok, also hätte deine Frage lauten müssen:
    Sende bitte mal den Inhalt deines Gradle-Files, damit ich sehen kann, welche Libs du benutzt.
    Diese Frage wäre nicht irrelevant, sondern sehr treffend gewesen.


    Obwohl ich auch da nicht verstehe, warum das gleiche und gleich konfigurierte Studio bei "Project new" eine andere Lib-Version verwenden sollte als bei "new. xml layout"


    Du hast aber nach der Android Version gefragt, die ich einsetze bzw für die ich entwickle.


    Und da du jetzt antwortest: "Es ist normal, das das Studio zwei verschiedene Constraint-Layouts erzeugt"


    Bedeutet das: "Auch ohne nach der Android-Version zu fragen, hätte ich dir sagen können, das ist normal beim Studio."


    Denn sonst hätte deine Antwort so lauten müssen:
    Android Studio verwendet zwei Layouts, wenn die Android-Version kleiner als x ist.


    Aber drehen wir's doch mal um:
    Die Antwort habe ich dir jetzt verspätet gegeben. Welche Schlüsse ziehst du jetzt aus meiner Android-Version?
    Denn wenn die Android-Version relevant wäre, dann müsste es jetzt eine Antwort geben, in der auf die Version Bezug genommen wird.
    Etwa so:
    Jaaaa, bei Version XY gibts ein Problem.


    Wenn es eine solche Antwort nicht gibt, dann ist die Frage nach der Version irrelevant.


    Ich mache auch nichts besonderes. Ich habe die Standard-Einstellungen vom Studio verwendet und weiß nicht mal, wie und auf welche Libraries man umstellen kann.
    Ich weiß nur, das ich einige Sachen mache, die ungewöhnlich sind.
    Dazu gehört zu Beispiel, das ich viele Layout.xml's habe, die per Include in eine main_layout.xml eingebunden werden.


    Es braucht sich aber jetzt keiner noch eine große Mühe machen, ich habe alle Container auf Grid-Layouts umgestellt, und damit kann ich alles so positionieren, wie ich will.



    Ach ja, hier noch die "hoffentlich relevanten" ( grins ) Stellen aus Meinen Gradle-Files:
    Wie man sieht, war die Frage danach sehr wohl relevant, denn wie du richtig vermutet hast, stehen da unterschiedliche Libs für Constraints.


    NUR: Ich habe da nichts gemacht. Ich habe das fehlerhafte Projekt vor einigen Monaten erstellt und das, was jetzt AndroidX verwendet vorgestern.
    Ich wüsste nicht,das ich da irgendwo "rumgeschraubt" habe.


    Aus build.gradle (Prject):
    classpath 'com.android.tools.build:gradle:3.5.2'und aus der build.gradle (Modules): dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.android.support:gridlayout-v7:28.0.0'
    }


    UNd wenn ich ein neues Projekt anlege, dann steht in build.gradle (Modules):


    dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'

    Ich beantworte sinnlose Fragen grundsätzlich nicht.
    Ich habe geschrieben, das der Fehler bei verschiedenen Handys mit verschiedenen Android Versionen auftritt, und daher nehme ich an, es hat nichts mit der Android-Version zu tun.
    Und wenn es so wäre: Es wäre längst bekannt geworden, wenn Android X.Y keine Buttons am unteren Displayrand darstellen kann.


    Es muss also etwas sein, was ich mache, aber üblicherweise so nicht gemacht wird.
    Und da denke ich an meine vielen Displays.
    Und dabei ist mir eben aufgefallen, das ein und dieselbe Studio-Version zwei verschiedene Arten von Constraint-Layouts erzeugt.
    Einmal mit Android: und mit AndroidX:
    Also bin nicht ich es, der jetzt plötzlich mit AndroidX arbeitet, sondern das Studio macht das gezwungenermaßen so.
    Ich weiss noch nicht mal, worum es da eigentlich geht.

    Neue Erkenntnisse:
    Ich habe mal ein komplett neues Projekt aufgesetzt.
    Im Layout nur ein Textfeld und ein Button.
    Constraints beim Button nur nach unten und rechts, und der Button erscheint unten.


    Nur in meinem ursprünglichen Projekt geht es nicht.


    Der Unterschied:
    Die neue funktionierende App hat bei der Erzeugung das Layout.xml selbst automatisch erstellt.


    Da die App, bei der es nicht funktioniert, mehrere Layouts hat, habe ich diese über das Menü File , New, XML, LayoutXML file erstellt.
    Und mit den so erstellten XML-Files geht es nicht.


    Mir ist erst jetzt aufgefallen, dass in den beiden Files die Definition des Constraint Layouts unterschiedlich ist.


    Im funktionierenden XML-File steht:


    <androidx.constraintlayout.widget.ConstraintLayoutIm XML-File, das über das Menü erzeugt wird steht:<android.support.constraint.ConstraintLayout

    Danke für die schnelle Antwort, aber das habe ich alles schon probiert.
    Ich habe den Button zum Beispiel in alle 4 Richtungen an den Rand des Constraint-Layouts verbunden.


    Im Editor erscheint der Button dann zentriert in der Mitte des Displays, aber im Emulator oder auf dem Gerät erscheint er ganz oben und überdeckt meinen Text.
    Wenn ich ihn mit der Maus nach unten ziehe, verändert sich ein Parameter layoutConstraint_Vertical_Bias ( ich denke 0 bedeutet oben, 1 bedeutet unten )
    Im Editor verschiebt er sich auch nach unten, aber im Emulator oder auf dem Gerät ist er wieder ganz oben..
    Das einzige, was hilft ist, den Parameter Margin zu erhöhen.


    Die gleiche Reaktion passiert auch, wenn ich den Button nicht an den oberen Layout-Rand binde, sondern an den unteren Rand des Edit-Feldes.


    Ich verstehe auch nicht, warum ich alle 4 Richtungen angeben muss.
    Es sollte doch eigentlich reichen, den Abstand rechts und unten festzulegen.

    Hallo,
    ich hab schon wieder ein ziemlich nerviges Problem und kann es einfach nicht lösen, obwohl es sich einfach anhört.


    Ich habe ein Layout mit (vorläufig) einem EditText-Feld und einem "Cancel"-Button.


    Ich möchte folgendes erreichen:


    1. Das Textfeld soll später unterschiedlich lange Texte ( von etwa 1 ... 10 Zeilen ) aufnehmen und muss daher mit dem Inhalt von oben in der Höhe "wachsen".
    Also die erste Zeile des Textinhalts soll immer ganz oben auf dem Display sein, und es soll bei sehr viel Text nicht mehr als 90% der Displayhöhe beanspruchen.


    2. In den unteren 10% des Displays möchte ich eine Zeile mit mehreren Buttons ( momentan zum Testen aber nur einer ) darstellen.


    Mein Problem: Egal, welchen Layout-Container ich verwende, irgendwas geht immer nicht.


    Beispiel :
    Bei einem Relative Layout funktionieren keine Margins. ( Ihr könnt's mir glauben, es sollte gehen, es geht aber nicht !) Somit kann ich unterschiedlich hohe Buttons, Switches, Checkboxen u.s.w. nicht in einer Höhe darstellen.


    Bei einem Constraint-Layout ( XML habe ich unten angegeben ) funktionieren keine Constraints, die an den unteren Containerrand gekoppelt werden. Das Ergebnis: Der Button steht mitten im Edittext, statt am unteren Displayrand.


    Hat jemand eine Idee, wie man sowas möglichst einfach hinbekommt?
    Das kann doch eigentlich nicht so schwer sein, aber ich knacke jetzt schon 4 Tage daran rum.



    Laut Doku soll das das Gleiche sein . System.rc ruft intern auch Runtime.getRuntime().gc(); auf.


    Ich weiß jetzt allerdings gar nicht, ob das Problem überhaupt noch eines ist.
    Enstanden ist es, als ich noch für jedes Display eine eigene Activity benutzt habe. Der Speicherbedarf war extrem und da ist dann mein Handy "eingefroren".
    Ich dachte, das Problem wäre weg, wenn ich nur eine einzige Activity habe.
    Also habe ich meine App umgeschrieben und NICHT auf dem Handy sonderrn erstmal im Emulator getestet, wie es da mit dem Speicher ist.
    Mit der einzelnen Activity war der Verbrauch zwar deutlich geringer, aber er stieg wie in meinem letzten Post geschrieben immer noch an, und ich dachte, das sei bestimmt nicht normal.
    Wenn du aber sagst, das der GC etwa bei 70% erst Speicher freigibt, dann kann es gut sein, das das Verhalten meiner App doch normal ist.


    Ich werde es ja sehen, wenn sie wieder funktionsfähig ist.
    Ich knacke da nämlich noch an einem anderen ünlösbaren Problem, aber das ist ein andere Thread.


    Also sage ich erstmal vielen Dank für deine Mühe und Geduld.

    Ich habe jetzt 2 Stunden gesucht, ich weiß nicht, wie ich die Belegung des Heaps in Prozent rausbekomme.
    Ich sehe im Profiler nur, das meine App mit einem Verbrauch von 36MB startet, und das bei den Wechseln der Fenster immer etwas zwischen 100 - 500 KB dazu kommen ( Also von A nach B kommt was hinzu, und von B nach A zurück auch wieder.


    Oben im Profiler ist ne gestrichelte Linie bei 64MB. Wenn das die Heapgröße ist, dann wäre also bei Start der verwendete Heap ca. 50%.


    Und zum GC. Das glaube ich schon, das da spezielle Feinheiten sind.
    Ich habe ja auch nur gesagt, was er im Prinzip macht.
    Aufgerufen muss er werden, sonst macht das keinen Sinn, dann wäre er toter Code.
    Und unbenutzen Speicher freigeben macht er auch, und vermutlich auch eine Defrargmentierung


    Das Einzige, was ich mir noch vorstellen kann, wäre, das er erst dann Speicher freigibt, wenn keiner mehr da ist.
    In diesem Fall wäre mein hochschukeln des Speichers normal.
    Dagegen spricht aber, das meine App auf dem Handy zum Freeze desselben führt.


    Man kann den GC auch vom Profile Menü aus aufrufen. Wenn ich das mache, wird zwar etwas freigegeben, aber nicht alles.
    Das Hochschaukeln geht weiter.


    Hier ein Beispiel:
    A gestartet : 36,0 MB
    A startet B : 36,6 MB
    B zurück zu A 36,8 MB
    A startet B: 36,9 MB
    B zurück zu A 37,0 MB
    A startet B 37,1 MB


    u.s.w.


    Garbage Collector per Menü aufrufen : 36,7 MB ( also 700MB nicht freigegeben )


    Wieder wie oben weitergetestet:
    Speicher steigt wieder wie oben an.


    Garbage Collector wieder per Menü aufgerufen 38,1 MB


    u.s.w.


    Der Speicher steigt und steigt.



    Also stelle ich die Frage mal anders rum.
    Wenn der Heap bei Programmstart 50% belegt ist, was sagt das dann aus ?


    Was muss ich bei Android /Java machen, damit der Speicher, den meine Steuerelemente belegen, wieder freigegeben wird ?


    Selbst wenn ich genau wüsste, wie der GC funktioniert, nützt es mir nix, wenn es keine Möglichkeit gibt, ihn so zu nutzen, das der unbenutzte Speicher freigegeben wird. Und genau das ist mein Problem bzw meine Frage

    Zum Thema Heap: Was nützt diese Antwort, bzw. welche Schlüsse ziehst du aus dieser Info . ;)
    Ich sehe da den Zusmmenhang mit dem Problem nicht.


    Nein, ich verwende Android Studio und das mit dem Speicher sehe ich im Profiler.
    Ich müsste erstmal gucken, wie man im Emulator die Heapgröße sehen kann, bzw ob das für einen Emulator, der auf einem PC läuft , überhaupt sinn macht. Bisher habe ich nix gesehen, wo man es erkennen kann.


    Wie sich ein Garbage Collector verhält, weiß ich.
    Das ist auch irrelevant.
    Er müsste entweder zyklisch vom System aufgerufen werden , oder bei bestimmten Ereignissen ( wie zu Beispiel wen eine App zerstört wird) und dann Speicher, der nicht mehr referenziert wird freigeben.
    Genau das macht er aber nicht, und das kann zwei Ursachen haben:
    1. Er wird gar nicht aufgerufen ( habe ich ausgeschlossen, weil ich ihn testweise selbst aufgerufen habe ( System.gc() ).
    und der Speicher ist trotzdem noch belegt.
    2. Bleibt nur Möglichkeit 2, der GC erkennt nicht, das der Speicher nicht mehr verwendet wird.
    Also muss man dafür sorgen, das er es erkennt.
    Ich habe gefragt, ob es eine Möglichkeit wie bei C gibt (new und delete).
    Gibts bei Java nicht.
    Du sagtest, man solle die Objektzeiger auf Null setzen.
    Hab ich gemacht, hilft auch nicht.
    Es hat nicht geholfen, weil es gar nicht der von mir allokierte Speicher ist, der das Problem verursacht, also hilft es auch nicht, den von mir allokieretn Speicher auf null zu setzen oder sonstwas damit anzustellen.


    Das Einzige, was helfen wird ist, wenn es eine Möglichkeit gäbe, die aus den Resourcen "geholten" Steuerelemente wieder zu zerstören.

    Noch eine Idee/Frage zu diesem Thema.
    Ich weiß nicht, ob das geht, aber es könnte ja mal einer versuchen:


    Könnte man nicht mehrere Buttons in einer Button-Group zusammenfassen, oder einen unsichtbaren Container drumherum basteln (z.B ein Layout ).


    Und dann könnte man versuchen, statt der einzelnen Buttons nur die Visibility der Gruppe oder des Containes zu manipulieren.

    Also nochmal zusammenfassend:
    1. Die Größe des Speichers, der angefordert und nicht freigegeben wird, hängt von der Größe des Arrays für die Listenelemente des Listviews ab.
    2. Es passiert auch bei Displays, die kein Listview haben, sondern nur einfache Buttons und Editfelder.
    ( ich habs mit einem einfachen Einstellungsdialog probiert, 3 Buttons, 5 Editfelder und ein paar Beschriftungen, und da passiert es auch ).


    Da die Anzahl der darzustellenden Listitems der Anzahl der Arrayelemente enspricht, nehme ich mal an, es passiert generell beim Erzeugen der Steuerelement (Buttons, Listitems ) usw aus den Resourcen und das war ja auch deine anfängliche Vermutung.


    Aber : Egal was ich jetzt benutze ( ViewFlipper, Fragmente, separate Apps, Eine App und SetContentView u.s.w. ......
    Es werden immer Steuerelemente aus Resourcen "geholt", also wird immer Speicher verbraucht und nicht freigegeben, und kann ich machen was ich will, mehrere Displays gehen bei Android grundsätzlich nicht, weil irgendwann der Speicher aus dem Ruder läuft.


    Es ist nur so: Bei mir ist es nur aufgefallen, weil ich teilweise EXTREM VIELE Steuerelemente habe, und somit auch immer viel Speicher angefordert wird. Das wird normalerweise bei anderen Usern nicht der Fall sein, und darum ist es vielleicht noch niemandem aufgefallen.

    Na ja, das wäre ein Bisschen zu einfach zu sagen : Java ist die Sprache der Wahl, aber benutzen sollte man sie nicht.
    Strings sollten immer funktionieren, egal ob groß oder klein.
    Und wenn nicht, dann hat man was bei der Umsetzung der Programmiersprache falsch gemacht und nicht bei der Benutzung dwr Sprache.


    Das mit dem Static final habe ich nur erwähnt, weil da offensichtlich was nicht zusammenpasst:
    Lege ich die Arrays dynamisch an, tritt das Problem nicht oder weniger stark auf.
    Verwende ich ein statisches Array, dann wird dauernd Speicher angefordert. und nicht freigegeben.
    Eigentlich sollte man es eher umgekehrt erwarten, oder?


    Neue Erkenntnis: OK, das mit dem nicht zusammen passen ist geklärt. Wenn ich ein dynamisches Array verwende, enthält das deutlich weniger Elemente als das Statische. Der Effekt erklärt sich also dadurch, das der zusätzlich angeforderte und nicht freigegebene Speicher von der Größe des Arrays abhängt, welches die Listenelemente definiert. Der Mehrverbrauch fällt also bei kleinen Arrays nicht so sehr auf, ist aber trotzdem da.

    Also: Es hat definitiv nichts mit von mir allokiertem Speicher zu tun, sondern ist ein internes Problem


    Ich habe es jetzt mal weiter reduziert.
    Ich allokiere jetzt GAR nichts mehr ( kein new usw ).
    Ich schalte jetzt nur noch mit ViewFlipper zwischen einem Haupt-Display und einem Sekundär-Display mit einem ListView hin und her,
    Die Listitems hole ich aus einerm Array aus der CustomAdapter Klassse, das Array wird nicht verändert:
    private String [] taskTitlesAll = {
    "Titel1",
    "Titel2", u.s.w.


    "Titel52",
    "Titel53"
    };





    und der Speicherverbrauch steigt und steigt bei jedem Umschalten.


    Es tut mir Leid, aber für mich sieht das nach einem Android Bug aus.

    Ich denke, es hat alles nichts damit zu tun, was du vermutest.


    Ich habe jetzt zum Beispiel nur noch eine einzige App.
    Hier passiert das Gleiche, und da diese App während des Tests niemals beendet wird und immer aktiv bleibt,
    kann es nichts mit Beenden von Apps zu tun haben.


    Auch die Frage nach der Größe ist unerheblich.
    Wenn es ein einziges Byte wäre, dann kann ich bei 1GB Speicher 1 Million mal umschalten, dann knallt's
    Wenn es um 500MB geht, knallt es beim ersten Umschalten.
    Das ist der einzige Unterschied.
    Aber das Problem, das dauernd neuer Speicher angefordert wird bleibt bestehen.


    Aber ich bin schon einen Schritt weiter, obwohl ich mir's immer noch nicht erklären kann.


    Folgende Bedingungen:
    Eine einzige Activity mit einem Main Display.
    (Da sind die ca. 80 Buttons drauf, einer davon schaltet per ViewFlipper auf ein anderes Sekundär-Display um.
    Per Back-Button schalte ich vom Sekundär Display auf das Main Display zurück.


    Das andere Display beinhaltet nur einen ListView, der mit einem Custom Adapter verbunden ist.


    Das Sekundäre Display verwende ich für zwei Fälle:


    1. Es soll eine Liste mit insgesamt 54 möglichen Aufgaben-Titeln anzeigen.
    ( Also steht dann da in der Listview untereinander Aufgabe1, Aufgabe2 ..... Aufgabe54 )
    Da die Liste für diesen Fall konstant ist, habe ich diese Aufgaben-Titel als static final string [] taskTitles = { "Aufgabe1","Aufgabe2" ....... }; angelegt.


    2. Es soll eine Liste mit den Aufgaben anzeigen, die jemandem zugeordnet wurden.
    ( Also z.B. jemand hat 3 Aufgaben bekommen, und zwar Aufgabe 5, Aufgabe 14 und Aufgabe 45 )
    Hier habe ich eine globale Variable String [] taskTitles; angelegt


    Wenn im Hauptfenster der Button "Alle möglichen Aufgaben" angeklickt wird, weise ich dem CustomAdapter die statische Liste zu:
    // Statische Aufgaben-Liste zuweisen (54 Stk.) customAdapter.taskTitles = taskTitles;// Sekundärdisplay anzeigen viewFlipper.setDisplayedChild( DISPLAY_TASKLIST );


    Wenn im Hauptfenster der Button "Zugewiesene Aufgaben" angeklickt wird, mache ich das Gleiche, nur diesmal erzeuge ich das Array mit den Aufgabentiteln dynamisch:


    // Dynamische Liste mit zugewiesenen Aufgaben erzeugen // (numberOfAssignedTasks ist irgendwas zwischen 1 und 16) taskTitlesAssigned = new String [ numberOfAssignedTasks ];// Dynamische Liste zuweisen customAdapter.taskTitles = taskTitlesAssigned;// Sekundärdisplay anzeigen viewFlipper.setDisplayedChild( DISPLAY_TASKLIST );In der onKeyDown reagiere ich auf den Back Button und schalte auf das Main Display zurück:public boolean onKeyDown(int keyCode, KeyEven
    {
    if ( keyCode == KeyEvent.KEYCODE_BACK )
    {
    switch(display) // Welches Display ist gerade angezeigt?
    {
    case DISPLAY_TASKLIST: // Das Sekundärdisplay ist aktiv
    display = DISPLAY_MAIN; // Auf Hauptdisplay zurück
    break;// Hier kommen noch weiter, sind aber uninteressant, passier genau das Gleiche
    default:
    return super.onKeyDown(keyCode, event);
    }
    viewFlipper.setDisplayedChild(display); // Auf das gewünschte Display zurückschalten// Und hier gebe ich die dynamisch allokierte Liste wieder frei........ ( Ist das so richtig ?)
    taskTitlesAssigned = null;


    System.gc();


    return true;
    }


    return super.onKeyDown(keyCode, event);}Und jetzt das Merkwürdige:Das Hin-Und Herschalten mit der dynamischen Liste funktioniert ohne wachsenden Speicher.Zeige ich aber die statische Liste im Sekundärfenster an, wird beim Aktivieren des Sekundärfensters Speicher angefordert, Beim Rückschalten auf das Hauptfenster wieder.Und wenn ich wieder auf Sekundär schalte wieder.

    Also erstmal vielen Dank, was ihr euch ( speziell jgimuc .... du solltest dich in meister yoda umbenennen, klingt ähnlich, triffts aber besser ) für eine Mühe mit mir macht.


    Also, das mit dem Speicherproblem ist so:
    Ich hatte anfangs einfach zwischen den Layouts umgeschaltet.


    Dann habe ich gelesen, das das Mist ist, wenn man mehrere "Fenster" hat, solle man das mit einzelnen Activities machen.
    Die Activities selbst sind sehr umfangreich ( z.B. hat die Hauptaktivity alleine etwa 80 Image-Buttons ).
    Es werden Threads für eine TCP/IP Kommunikation gestartet, List Views, jede Menge Klassen usw.
    Und das braucht natürlich alles Speicher.
    Dann habe ich mit viel Aufwand alles umgestellt, und war zufrieden, bis ich gemerkt habe, das mein Handy nach ein paar Umschaltungen träge wurde.


    Du hast recht: Ich habe meine Speicherverwaltung nicht im Griff. Ist aber auch kompliziert.
    Bei C rufe ich eine delete-Funktion auf und das Objekt ist zerstört.


    Bei Android setze ich die Zeiger auf die Objekte ( wie du empfohlen hast ) auf null und ..... nix passiert, der Speicher ist immer noch weg.
    Ich hätte eigentlich auch zwei Dinge erwartet.


    Entweder, wenn die Activity beendet wird, ist auch der belegte Speicher freigegeben. Dann muss ich die Objekte beim Neustart wieder neu erzeugen.
    Oder der Speicher bleibt allokiert, dann muss es aber auch eine Möglichkeit geben, die alten Objekte wieder weiterzunutzen, wenn die Activity neu gestartet wird.
    Beides ist aber scheinbar nicht der Fall.


    Also wollte ich rauskriegen, wer da den Speicher verbraucht, habe eine neue Mini-App geschrieben und rausgefunden, das es schon bei den Steuerelementen mit findViewById passiert, aber bestimmt bleibt auch der andere Speicher blockiert.


    Ich habe eine generelle Antwort erwartet, wie man mit einem solchen Problem umgeht ( und sie auch bekommen, nur funktionierts scheinbar immer noch nicht richtig ).


    Mein aktueller Stand
    Im Internet hatte ich an anderer Stelle gelesen, man könne auch das mit den vielen Activities vergessen und, wenn man mehrere Fenster hat, den ViewFlipper verwenden. ( Oder, wie auch du sagtest, Fragmente ).


    Helfen würde beides schon, denn dann werden nicht dauernd neue Objekte angelegt, weil man ja immer innerhalb einer einzigen Activity bleibt.


    Aber, wie schon befürchtet, klappt es anfangs immer gut, nur stolpert man später wieder über das nächste Hindernis.
    Das erste ( das das mit dem Back-Button nicht geht ) habe ich gelöst.
    Die CompatActivity hat tatsächlich KEINE onBackPressed. Jedenfalls bekomme ich immer eine Fehlermeldung, das man eine Methode einer Klasse nur überschreiben kann, wenn die Klasse sie implementiert, und das deute ich mal als onBackPressed oder so gibts bei Activities nicht, nur bei FragmentActivities.
    ich hab's aber mit der onKeyDown Methode hinbekommen. Wenn man's weiß, ist es logisch. Man kommt nur nicht drauf ;)


    Jetzt habe ich das nächste Problem:
    Ich habe eine ListView mit einem CustomAdapter. Die Menge der Listeneinträge ist dynamisch. Das hat bisher gut funktioniert, weil zur Anzeige der Liste bisher eine Activity gestartet wurde, die die Liste und den Adapter erzeugt und dann anzeigt.
    Ich muss jetzt eine Möglichkeit finden, dem Adapter eine neue Liste zuzuweisen, ohne immer einen neuen Adapter zu erzeugen., denn sonst habe ich wieder das Speicherproblem

    Das mit dem Lahmlegen des Handys passiert nur bei meiner eigentlichen App, die aus einigen tausend Zeilen Code besteht und darum zu groß und unübersichtlich ist, um sie hier darzustellen.


    Darum habe ich nochmal eine Mini-App geschrieben, die nur dazu da ist, das Problem zu demonstrieren.


    Die kleine , hier angegebene Demo belegt nur sehr wenig Speicher und das legt mein Handy natürlich nicht lahm, bzw. würde das erst nach tausenden Schaltversuchen machen. Man sieht bei dieser kleinen Demo aber deutlich im Emulator/Profiler, das sie Speicher belegt und nicht freigibt.


    Nur die eigentliche App, die ich hier der Größe wegen NICHT angegeben habe, belegt wesentlich mehr Speicher, und da sind unsere Handys bereits nach 5 Mal hin und herschalten nicht mehr bedienbar.


    Ich komme eigentlich aus der C-Ecke und bin es da gewohnt, das man das, was man reserviert, auch selbst wieder freigibt. Und es wäre schön gewesen, wenns bei Android auch so eine Möglichkeit gegeben hätte.


    Aber nochmal zurück zu meinem eigentlichen Problem:
    Das ist so: Ich möchte irgendwas erreichen, lese mich durch ziemlich viele unverständliche Tutorials und Dokus und entscheide mich dann für eine Methode, die mir halbwegs sinnvoll erscheint.
    Nachdem ich monatelang an der App programmiert habe, laufe ich irgendwann in eine Sackgasse, wo mir dann jemand sagt : "Das kannste so nicht machen, das musst du ganz anders, nämlich so machen".


    Und dann fange ich wieder von vorne an, programmiere wieder Monate und laufe in die nächste Sackgasse, wo mir wieder jemand Anderes sagt, das geht so auch nicht, du musst das hier nehmen.


    Genau so ist es mir jetzt wieder ergangen.
    Mir hat jemand empfohlen, den LayoutSwitcher zu verwenden. Ich hab mich da eingelesen, und siehe da: Mein Speicherproblem ist weg.


    Jetzt habe ich alles umgestellt und stelle fest: Jetzt geht das mit dem Back-Button nicht mehr, weil ich jetzt nicht mehr mehrere, sondern nur noch eine Activity habe.
    Ich dachte: Kein Problem, fängst du einfach das onBackPressed ab ..... Pustekuchen. Geht bei Activities nicht ( keine Ahnung, warum nicht ).


    Also werde ich wohl jetzt deinen Rat befolgen und mich in das Thema Fragmente einlesen, alles umschreiben um dann am Ende wieder festzustellen, das Fragmente leider keine Buttons unterstützen oder nur in chinesischer Sprache funktioniern..