ExpandableListView - getChildrenCount() ist null

  • Antworten:39
  • OffenNicht stickyNicht beantwortet
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.297

31.08.2016 20:47:46 via Website

Ja das Android Konzept ist schon noch mal was für sich, ich meinte Jetzt Java als reine Programmiersprache.
Wenn man diese im Android Umfeld einsetzt ist es nochmal was anderes.
Ist wie C# für Android mit Xamarin, das ist ja auch nicht nur reines C#

LG Pascal //It's not a bug, it's a feature. :) ;)

  • Forum-Beiträge: 85

31.08.2016 20:53:03 via Website

Pollen (aktualisieren der RequestId alle Sekunde ist TODLICH!

waaa...Warum? :'(

  1. Wenn du unbedingt pollen willst, dann nimmst du den gleichen AsyncTask aber eine neue Instanz mit neuem Callback, sodass du die Daten anders verarbetien kannst.
    Aus dem Callback kannst du ja dann Daten in die ListView schreiben.

Okay, hier meine neue Funktion:

private String recendReqID = "";
private void submitRequest(String url){
    Request.receivedDataListener rdl = new Request.receivedDataListener(){
        @Override
        public void onReceiveComplete(String result){
            recendReqID = result;
            lblRequestID.setText(result);

            Request.receivedDataListener recDListener = new Request.receivedDataListener(){
                @Override
                public void onReceiveComplete(String result){
                    if(result.equals("0 rows returned")) {
                        SystemClock.sleep(1000); //Warte für eine Sekunde
                        //Wie rufe ich jetzt hier einen neuen Request auf? Die Daten sind noch nicht vorhanden
                    } else {
                        try{
                            JSONArray jObj = new JSONArray(result);
                            JSONObject obj = jObj.getJSONObject(0);
                            String val = (String) obj.get("value");
                            String da = (String) obj.get("date");

                            listDataHeader.add(recendReqID);
                            List<String> data = new ArrayList<String>();
                            data.add(val);
                            data.add(da);

                            listDataChild.put(listDataHeader.get(listDataHeader.size() - 1), data);
                            listAdapter = new ExpandableListAdapter(ma, listDataHeader, listDataChild);
                            expandableListView.setAdapter(listAdapter);
                        } catch(Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            };

            String pollRequest = new String("irgendeineWebsite" + recendReqID);
            Request pollReq = new Request(recDListener);
            pollReq.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,pollRequest);
        }
    };

    Request r = new Request(rdl);
    r.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,url);
}

Wie rufe ich jetzt hier einen neuen Request auf, der erneut überprüft, ob die Daten vorhanden sind (siehe Kommentar)?

  • Forum-Beiträge: 2.209

31.08.2016 21:04:55 via Website

P.S ich ziehe mich jetzt ein bischen raus, verfolge aber ... wenn drei Quasseln bringt das nichts :-)
.

Kurz nur dazu - wird dir Pascal wahrscheinlich erklären

Pollen (aktualisieren der RequestId alle Sekunde ist TÖDLICH!

Deswegen mein Tipp an Dich : TCP Client/Server - das hatte seinen guten Grund

— geändert am 31.08.2016 21:05:42

Liebe Grüße - Stefan
[ App - Entwicklung ]

Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.297

31.08.2016 21:15:59 via Website

Wie du das aufrufst?
Schon mal was von rekursion gehört?
da wo der kommentar steht kannst du doch einfach deine private void submitRequest(String url) Methode mit der passenden URL wieder aufrufen oder?
Pass aber auf dass keine Endlosschleife entsteht :D

Zum pollen:

Da gibt es mehere Gründe:
1. Es werden dauernd Daten geschickt (falls die App mobil eingesetzt wird auf jeden Fall nicht schonend fürs Datenvolumen)
2. Es belastet das Netzwerk (wird im Heimsetz kein Problem sein, denke aber mal an ein Firmennetz an in dem Jede Applikation pollt...)
3. Es kostet Energie (Akku wird schneller leer...)
4. Es gibt bessere Lösungen wie TCP oder FCM etc...
5. Wenn du nehmen wir mal an x Geräte hast die auf den gleichen Server pollen, wieviele dürefen es dann sein bevor der Server überlastet ist oder gar abstürzt etc..

Ich weiß im privaten Bereich vernachlässigt man sowas gerne, aber ich hab meine Gründe solche Dinge auch aus Fitem-Softwareentwickler sicht zu betrachten.
Kannst du schon so machen, stören wirds auch nicht, aber beachte die Punkte oben

LG Pascal //It's not a bug, it's a feature. :) ;)

  • Forum-Beiträge: 85

31.08.2016 21:48:18 via Website

Ich hab es nun mit einer zweiten Funktion gelöst da sonst die "submitRequest" nochmal durchgeführt worden wäre:

private String recendReqID = "";
private void submitRequest(String url){
    Request.receivedDataListener rdl = new Request.receivedDataListener(){
        @Override
        public void onReceiveComplete(String result){
            recendReqID = result;
            lblRequestID.setText(result);
            pollData(result);
        }
    };

    Request r = new Request(rdl);
    r.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,url);
}

private void pollData(final String reqID){
    Request.receivedDataListener recDListener = new Request.receivedDataListener(){
        @Override
        public void onReceiveComplete(String result){
            if(result.equals("0 rows returned")) {
                SystemClock.sleep(1000); //Warte für eine Sekunde
                pollData(reqID);
            } else {
                try{
                    JSONArray jObj = new JSONArray(result);
                    JSONObject obj = jObj.getJSONObject(0);
                    String val = (String) obj.get("value");
                    String da = (String) obj.get("date");

                    listDataHeader.add(recendReqID);
                    List<String> data = new ArrayList<String>();
                    data.add(val);
                    data.add(da);

                    listDataChild.put(listDataHeader.get(listDataHeader.size() - 1), data);
                    listAdapter = new ExpandableListAdapter(ma, listDataHeader, listDataChild);
                    expandableListView.setAdapter(listAdapter);
                } catch(Exception e){
                    e.printStackTrace();
                }
            }
        }
    };

    String pollRequest = new String("website" + recendReqID);
    Request pollReq = new Request(recDListener);
    pollReq.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,pollRequest);
}
  1. Es werden dauernd Daten geschickt (falls die App mobil eingesetzt wird auf jeden Fall nicht schonend fürs Datenvolumen)

Wie würde das denn mit der TCP Methode aussehen? Was ich so ergooglet habe würde das so aussehen: http://stackoverflow.com/questions/10673684/send-http-request-manually-via-socket

Pollen würde ich da ja trotzdem (wenn ich den Google Service nicht nutze)? Bräuchte das dann weniger Datenvolumen wenn man die Verbindung offen hält?

— geändert am 31.08.2016 21:48:59

  • Forum-Beiträge: 2.209

31.08.2016 22:03:44 via Website

@Pascal , ich werfe mal schnell das hier rein

Nein , die Methode wäre eine REINE TCP Socket verbindung

 socket = new Socket(dstAddress, dstPort);
            ByteArrayOutputStream byteArrayOutputStream =
                    new ByteArrayOutputStream(1024);
            byte[] buffer = new byte[1024];
            int bytesRead;
            InputStream inputStream = socket.getInputStream();
            boolean connected = socket.isConnected() && !socket.isClosed();
            while ((bytesRead = inputStream.read(buffer)) != -1)
            {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
                response += byteArrayOutputStream.toString("UTF-8");
            }

und auf deinem Controller den TCP-Server (NICHT HTTP) in reinem C/C++ mit accept usw.
(Das Netz ist voll von Beispielen)

Pollen würde ich da ja trotzdem

Nein ,wenn die Verbindung steht , schickt der Controller nur dann was , wenn er was hat.

Info an dich : JEDER http Request - auch wenn nichts zurück kommt hat min 1,5 k request/response - header!!

— geändert am 31.08.2016 22:09:12

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 85

31.08.2016 22:14:36 via Website

Nein ,wenn die Verbindung steht , schickt der Controller nur dann was , wenn er was hat.

Das würde aber nur funktionieren, wenn beide Geräte im selben Netz sind bzw. sich die App direkt mit dem Controller verbindet?

  • Forum-Beiträge: 2.209

31.08.2016 22:19:25 via Website

Das würde aber nur funktionieren, wenn beide Geräte im selben Netz sind bzw. sich die App direkt mit dem Controller verbindet?

öhm - wieso das ?? ist doch schnuppe, ob du eine URL oder eine IP hast ...
Sprich , ob du einen http server oder einen TCP-Socket-Server auf der Kiste betreibst, ist gleichgültig
Connect ist Connect ....

— geändert am 31.08.2016 22:25:40

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 85

31.08.2016 22:27:48 via Website

Ich mach das ganze aktuell über eine Website, als man in the middle sozusagen, da das Ganze auch funktionieren soll, wenn ich nicht zu Hause bin.

  • Forum-Beiträge: 2.209

31.08.2016 22:36:38 via Website

Ich glaube, du stehst eben ein wenig auf dem Schlauch :-)

Wenn du nicht zu hause bist , rufst du derzeit auf : http://meinziel/blabla

das ist das Gleiche wie : socket = new Socket("http://meinziel/blabla", 80);

Nur mit dem grossen Unterschied, dass :

a) du beim connectaufbau nicht unsinnig jede sekunde 1,5K verbrätst
b) du wunderbar checken kannst, ob die sockertverbindung noch besteht und kannst reconnecten - das sind nur ein paar bytes. (Kannst ja noch Pings durch die gegend schieben)
c) und wenn du die Verbindung Aufgebaut hast, passiert vielleicht 2 stunden gar nichts - ergo , kein einziges byte über den Äther, bis der Controller was hat

Rechne mal bei deinem http - request für die zwei stunden : 3600 x 2 x 1,5 KBytes = 11MB für NIX
.
.
Oder halt FCM - wie Pascal angedacht hat - aber jede Sekunde einen httpRequest - na ja :-(

— geändert am 31.08.2016 22:40:14

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 85

31.08.2016 22:42:37 via Website

Ich verstehe es tatsächlich nicht. Wie kommt die Nachricht von meinem Controller über die Website an meine App, dass der Controller was hat, ohne das ich nachfragen muss? Der Controller kann es mir nicht sagen, da er in einem anderen Netz ist, die Website bzw. die Datenbank kann es mir auch nicht sagen, da es eben eine Website ist (oder kann ich mit JavaScript auf einen bestehenden WebSocket zugreifen?). Ergo muss ich doch immer noch nachfragen "wie siehts aus"? Wäre hilfreich, wenn du mir genauer erklären könntest, wie das zwischen Controller / App und Datenbank (Website) ablaufen soll?

— geändert am 31.08.2016 22:45:17

  • Forum-Beiträge: 2.209

31.08.2016 22:54:18 via Website

Ok, ich bin wohl wieder drin .. Pascal kann pause machen :-)

Ich werfe eine Gegenfrage in den Raum :

Dein Middle hat derzeit einen http-Server aufgebaut - gut und schön.
Es ist auch jetzt erst mal wurscht , wie der Middle die Daten vom Controller bekommt.

ABER : Der Middle kann auch einen TCP-Socket-Server laufen lassen halt nur nicht über http- vorgang wie oben beschrieben. (Stichwort : Datenvolumen)
Und wenn der Middle was Neues vom Controller hat , kann der ja an deine App schicken.
Du brauchst im Prinzip einen Push Service - da gibts auch noch andere Techniken auf Web basis (Node.js)

Auch die Verbindung vom Middle zum Controller kannst du jederzeit mittels TCP-Socket machen.
(Ein Relay - Das nenne ich dann Waschmaschine - Daten werden nur geschleudert)

Abgesehen davon : Es gäbe auch die Möglichkeit mittels DYNDNS direkt auf dem Controller zu landen.
Wenns mehrere sind, machste einen Port unterschied.

Bitte verstehe mich nicht falsch , es geht hier lediglich darum , dass du unnötig Datenvolumen verbrätst und
gerne schnell auf Zustände reagieren möchtest - da ist HTTP falsch an der Stelle.

— geändert am 31.08.2016 22:59:35

Liebe Grüße - Stefan
[ App - Entwicklung ]

Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.297

31.08.2016 22:58:52 via Website

Das geht nur wenn der Server TCP an sich unterstützt.
Wenn du nur einen reinen Webserver (mit php etc..) hast dann nicht, da du da keine dauerhafte TCP Verbindung aufrecht erhalten kannst.
Wir sind bisher davon ausgeganden dein Controller ist gleichzeitig der htp server und du hast ein Portforwarding nach außen. Damit würde das nämlich gehen. Ansonsten nur noch mit FCM, oder einem Server den man als TCP Server benutzen kann.
Die frage ist wie lange und wann löuft der Poll. Sind das nur ein paar Sekunden ist das zu verkraften, aber wenn das einige Stunden sind und dann noch laufen soll wenn die App geschlossen ist (BackgroundService) dann kann es kritisch werden.
Überleg mal 1 REquest pro Sekunde und nehmen wir pro forma mal 10 kb an Daten an.
in einer Minute wären das dann 10*60=600kb und das mal 60 = 36.000kbsind ca. 36mb, somit brauchst du pro Stunde laufzeit 36MB Daten. Bei den noch hohen Datenpreisen für mobile Daten würde ich mir das schon +überlegen om mir das "wert" ist. Wie gesagt je nach dem wie lange ein Poll läuft....

@Stefan: Wie gesagt, ein normaler WebServer unterstütz kein TCP, da ich nur übers http protokoll per php etc.. kann. Dafür kann ich aber umso einfacher von einem php Server eine FCM auslösen.

— geändert am 31.08.2016 23:00:35

LG Pascal //It's not a bug, it's a feature. :) ;)

  • Forum-Beiträge: 85

31.08.2016 23:01:03 via Website

Bitte verstehe mich nicht falsch , es geht hier lediglich darum , dass du unnötig Datenvolumen verbrätst und
gerne schnell auf Zustände reagieren möchtest - das ist HTTP falsch an der Stelle.

Ich möchte das auch gerne ändern da ich mir inzwischen bewusst bin, dass es zwar funktioniert aber es einen besseren Weg gibt.

Und wenn der Middle was Neues vom Controller hat , kann der ja an deine App schicken.

Wie genau setze ich sowas auf meinem Webserver um?

Abgesehen davon : Es gäbe auch die Möglichkeit mittels DYNDNS direkt auf dem Controller zu landen.
Wenns mehrere sind, machste einen Port unterschied.

Hm, lieber nicht. Erstmal einfach(er).

Wenn du nur einen reinen Webserver (mit php etc..) hast dann nicht, da du da keine dauerhafte TCP Verbindung aufrecht erhalten kannst.

Ich hab nur einen kostenlosen Webspace mit PHP / Datenbank und Co, geht also anscheinend nicht?`

Die frage ist wie lange und wann löuft der Poll.

Im idealen Fall ist das in 4 Sekunden pro Request erledigt. Hält sich also noch in Grenzen.

— geändert am 31.08.2016 23:04:45

  • Forum-Beiträge: 2.209

31.08.2016 23:03:22 via Website

@Stefan: Wie gesagt, ein normaler WebServer unterstütz kein TCP, da ich nur übers http protokoll per php etc.. kann

Ja sorry , ich hatte bis dato immer nur dedicated - denke ich manchmal nicht dran :-(

@Sharp :
Du siehst , beide - Pascal und ich würden dir anraten , den Vorgang nochmal zu überdenken
Falls das oben untergegangen ist - Node.JS ( wenn das bei dir geht ) wäre auch noch eine Möglichkeit

— geändert am 31.08.2016 23:04:24

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 85

31.08.2016 23:05:31 via Website

Node.JS ( wenn das bei dir geht )

Geht nicht, hab nur nen kostenlosen Webspace.

Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 9.297

31.08.2016 23:08:09 via App

Dann so lassen oder FCM

Was anderes bleibt dir nicht.

LG Pascal //It's not a bug, it's a feature. :) ;)

  • Forum-Beiträge: 2.209

31.08.2016 23:08:33 via Website

Dafür kann ich aber umso einfacher von einem php Server eine FCM auslösen.

Pascal ? - Beispiel bitte - liebschau ---
Das habe ich nämlich noch nicht umgesetzt .... Ich hatte eben schon nach einer C-Lösung gesucht ,
Aber PHP ginge zur Not auch :-)

EDIT : Gefunden , Ludy hat ja was schönes geschrieben - danke

— geändert am 31.08.2016 23:39:21

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 85

31.08.2016 23:11:47 via Website

Dann so lassen oder FCM

Ich denke, ich lasse es erstmal so und bastel am Controller. Vielen Dank für eure Hilfe (cool)

  • Forum-Beiträge: 2.209

31.08.2016 23:16:23 via Website

Ich denke, ich lasse es erstmal so und bastel am Controller. Vielen Dank für eure Hilfe

Keine Ursache, das machen wir gerne - und würden uns auch über ein paar Danke - Klicks freuen :-)

P.S Sei jetzt nicht fustriert, aber Blümchenmalerei wolltest du ja eh nicht haben :-)

Liebe Grüße - Stefan
[ App - Entwicklung ]