Laden und Verarbeiten von JSON-Daten aus PHP-Script

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von h00ligan, 29.05.2012.

  1. h00ligan, 29.05.2012 #1
    h00ligan

    h00ligan Threadstarter Junior Mitglied

    Beiträge:
    40
    Erhaltene Danke:
    0
    Registriert seit:
    22.03.2012
    Hey Leute :)

    Folgendes soll meine App leisten (im Großen und Ganzen):

    Ich habe in der Main-Klasse einen Button.
    Beim Klick auf diesen Button soll in einer anderen Klasse ein PHP-Script auf einem Webserver aufgerufen werden, welches JSON-kodierte Daten zurückgibt.

    Diese Daten sollen dann wieder zur Main-Klasse um dort benutzt zu werden.

    Ich habe bisher versucht es mit viel getrickse per Thread zu machen, allerdings bekomme ich öfter irgendwelche Fehler, weil ich nicht 100%ig mit der Thread-Verarbeitung vertraut bin.

    Mein Frage wäre im Grunde, wie ich mein Problem vielleicht besser und vor allem einfacher lösen könnte.
    Ich habe öfter mal was von AsyncTasks gelesen, allerdings konnte ich mit Hilfe der gefundenen Tutorials mein oben genanntes Problem nicht ordentlich nachbauen :(

    Gruß
     
  2. swordi, 29.05.2012 #2
    swordi

    swordi Gewerbliches Mitglied

    Beiträge:
    3,389
    Erhaltene Danke:
    441
    Registriert seit:
    09.05.2009
    asynctask ist sicher dein freund :)
     
  3. h00ligan, 29.05.2012 #3
    h00ligan

    h00ligan Threadstarter Junior Mitglied

    Beiträge:
    40
    Erhaltene Danke:
    0
    Registriert seit:
    22.03.2012
    Hast du vielleicht ein gutes Tutorial am Start?

    Ich hab schon so viel ausprobiert und nichts will irgendwie klappen :(

    Also AsyncTask in gleicher Klasse wie der Rest des Codes ist noch machbar, aber AsyncTask in anderer Klasse ist mir zu hoch :D

    Zumal das Programm auch "warten" soll, bis der AsyncTask beendet ist.
    Kann man das auch realisieren?

    Gruß
     
  4. DieGoldeneMitte, 29.05.2012 #4
    DieGoldeneMitte

    DieGoldeneMitte Android-Lexikon

    Beiträge:
    1,230
    Erhaltene Danke:
    256
    Registriert seit:
    05.02.2010
    Phone:
    Nexus 5X
    Tablet:
    Nexus 7 (2013)
    On does not simply walk into M^W^W^Wstop a GUI. :D

    Du kannst in den Listenern zu den GUI Elementen ein flag abfragen und nichts tun, solage es der AsyncTask nicht wieder freigegeben hat. (oder Enabled bei entscheidenden GUI-Elementen auf false setzen).
     
  5. swordi, 29.05.2012 #5
    swordi

    swordi Gewerbliches Mitglied

    Beiträge:
    3,389
    Erhaltene Danke:
    441
    Registriert seit:
    09.05.2009
    es gibt viele gute links zu dem thema

    ich möchte aber hier keine java einschulung geben :)
     
  6. Tom299, 30.05.2012 #6
    Tom299

    Tom299 Android-Experte

    Beiträge:
    602
    Erhaltene Danke:
    120
    Registriert seit:
    31.08.2011
    Wenn du mit dem AsyncTask nicht zurecht kommst, nimm doch einfach nen Handler, das bevorzuge ich auch immer.

    Mußt später halt dran denken, deine GUI auf dem UI-Thread zu aktualisieren:
    Code:
    			runOnUiThread(new Runnable() {
    				@Override
    				public void run() {
    					textView.setText("Blablabla");
    				}
    			});
    
     
  7. h00ligan, 30.05.2012 #7
    h00ligan

    h00ligan Threadstarter Junior Mitglied

    Beiträge:
    40
    Erhaltene Danke:
    0
    Registriert seit:
    22.03.2012
    Sorry Leute, ich steh grad voll aufm Schlauch.

    Ich kriegs einfach nich auf die Reihe...

    Ich denke ich weiss wovon ihr redet, aber ich bekomms nicht umgesetzt :(
     
  8. Tom299, 30.05.2012 #8
    Tom299

    Tom299 Android-Experte

    Beiträge:
    602
    Erhaltene Danke:
    120
    Registriert seit:
    31.08.2011
    Ich hab dir mal ein einfaches Beispiel gemacht:

    Code:
    package de.test;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Handler.Callback;
    import android.os.Message;
    import android.widget.TextView;
    
    public class HandlerExampleActivity extends Activity {
    	
    	private TextView tvTest;	
    	private Handler threadHandler;
    	private Thread countDownThread;
    	
    	public final static int ACTION_COUNTDOWN = 1;
    	public final static int ACTION_FINISH = 2;
    	
    	
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            
            tvTest = new TextView(this);
            setContentView(tvTest);
            
            threadHandler = new Handler(new Callback() {
    			@Override
    			public boolean handleMessage(Message msg) {
    				if (msg != null) {
    					if (msg.arg1 == ACTION_COUNTDOWN) {
    						final Integer counter = msg.arg2;
    						tvTest.setText(counter.toString());
    						return true;
    					}
    					else if (msg.arg1 == ACTION_FINISH) {
    						tvTest.setText("ENDE");
    						return true;
    					}
    				}
    				
    				return false;
    			}
            });
    		
            countDownThread = new Thread(new Runnable() {
    			@Override
    			public void run() {
    				int i = 10;
    				while (i > 0) {
    					Message msg = Message.obtain();
    					msg.arg1 = ACTION_COUNTDOWN;
    					msg.arg2 = i;
    					threadHandler.sendMessage(msg);
    					
    					try {
    						Thread.sleep(1000);
    					}
    					catch (InterruptedException ie) {
    						ie.printStackTrace();
    					}
    					
    					i--;
    				}
    				
    				Message msg = Message.obtain();
    				msg.arg1 = ACTION_FINISH;
    				threadHandler.sendMessage(msg);				
    			}
    		});
            countDownThread.start();
        }
        
    }
    
    Kommste damit klar? ;-)
     
  9. h00ligan, 30.05.2012 #9
    h00ligan

    h00ligan Threadstarter Junior Mitglied

    Beiträge:
    40
    Erhaltene Danke:
    0
    Registriert seit:
    22.03.2012
    Ich würde es wahrscheinlich irgendwie auf die Reihe bekommen, allerdings wüsste ich nicht, wie ich es auf meine Situation anpassen müsste :(

    Der Thread muss ja in einer anderen Klasse laufen.
    Am Ende des Threads muss ich in der Main-Klasse dann den Rückgabewert haben.

    Hier mal ein Code-Ausschnitt von meiner App, so wie es momentan läuft:

    Main.java:
    Code:
    ...
    final Scripty scripty = new Scripty();
    JSONObject datenJSON = scripty.getJSONforURL("http://www.de/blubb.php", "?typ=auto");
    
    //Hier soll er erst weitermachen, wenn die Funktion "getJSONforUR" beendet ist
    ArrayList<ArrayList<String>> datenArrayList = scripty.getArrayListForSpinner(datenJSON);
    
    Scripty.java:
    Code:
    public class Scripty {
    	String url = "";
    	String params = "";
    	Scripty context = this;
    	JSONObject jsonResponse;
    	
    	public JSONObject getJSONforURL(String targeturl, String urlparams){		
    		url = targeturl;
    		params = urlparams;
    		
    		System.out.println("url: " + url);
    		System.out.println("params: " + params);
    		
    		checkUpdate.start();	   
    	    
    		while(checkUpdate.isAlive()){
    			try {
    				synchronized(this) {
    					wait(50);
    					System.out.println("wait");
    				}
    			} catch (InterruptedException e) {
    
    			}
    		}
    
    		return jsonResponse;
    	}
    	
    
    	private Thread checkUpdate = new Thread() {
    		public void run() {
                try {
                    URL updateURL = new URL(url + params);
                    URLConnection conn = updateURL.openConnection();
                    InputStream is = conn.getInputStream();
                    BufferedInputStream bis = new BufferedInputStream(is);
                    ByteArrayBuffer baf = new ByteArrayBuffer(50);
    
                    int current = 0;
                    while((current = bis.read()) != -1){
                        baf.append((byte)current);
                    }
                    jsonResponse = new JSONObject(new String(baf.toByteArray()));
                    
                    System.out.println("ende");
                } catch (Exception e) {
                	e.printStackTrace();
                }
            }
        };
    }
    
    In dieser Form ist das Programm auch lauffähig, allerdings kann ich die Funktion "getJSONForURL..." nur 1 Mal in Main aufrufen, weil sonst der Fehler kommt: "Thread already started" (oder so ähnlich)

    Ich hoffe, dass mein Problem SO etwas deutlicher wird :D

    Gruß
     
  10. Tom299, 30.05.2012 #10
    Tom299

    Tom299 Android-Experte

    Beiträge:
    602
    Erhaltene Danke:
    120
    Registriert seit:
    31.08.2011
    Wenn du die Antwort in deiner "Main" brauchst, dann implementiert du dort den Handler (so wie ich im Beispiel).

    Den Handler übergibst du dann deiner Klasse und setzt dort die Message ab. Also genau wie in meinem Beispiel, nur daß ich den Thread in der gleichen Klasse habe, du hast es ausgelagert. Aber die Logik ist doch die gleiche.
     
  11. h00ligan, 30.05.2012 #11
    h00ligan

    h00ligan Threadstarter Junior Mitglied

    Beiträge:
    40
    Erhaltene Danke:
    0
    Registriert seit:
    22.03.2012
    Naja, habs jetzt mal versucht...

    Leider hab ich absolut 0 Ahnung wie ich es benutzen soll...

    Ich weiss weder wie ich die URL an den Thread übergeben soll, noch weiss ich, wie ich das Ergebnis des Threads (das jsonObjekt) wieder in die Main-Klasse kriege

    :(
     
  12. Tom299, 30.05.2012 #12
    Tom299

    Tom299 Android-Experte

    Beiträge:
    602
    Erhaltene Danke:
    120
    Registriert seit:
    31.08.2011
    gib deiner Klasse Scripty doch einfach nen Konstruktor mit dem Handler ...

    ich frag mich nur gerade, ob du datenJSON noch weiter verwendest?
    Code:
    final Scripty scripty = new Scripty();
    JSONObject datenJSON = scripty.getJSONforURL("http://www.de/blubb.php", "?typ=auto");
    
    //Hier soll er erst weitermachen, wenn die Funktion "getJSONforUR" beendet ist
    ArrayList<ArrayList<String>> datenArrayList = scripty.getArrayListForSpinner(datenJSON);
    
    Denn du übergibst es danach wieder an deine Scripty-Klasse. Das kannste dann auch gleich intern machen ;-)
     
  13. h00ligan, 30.05.2012 #13
    h00ligan

    h00ligan Threadstarter Junior Mitglied

    Beiträge:
    40
    Erhaltene Danke:
    0
    Registriert seit:
    22.03.2012
    Wie genau stelle ich das an? :D


    Also vielleicht noch zur Info: In der Scripty-Klasse stehen noch andere Funktionen. Ich habe nur die beiden Methoden zur Veranschaulichung rauskopiert.
    Somit wäre ein Konstruktor für die Scripty-Klasse nicht möglich, zumal ich innerhalb der Main-Klasse ja mehrmals etwas übergeben möchte.

    Desweiteren habe ich noch andere Klassen, die ebenfalls mit Scripty arbeiten, allerdings nur in ähnlicher Form. Deswegen muss ich alle Daten einzeln zurückgeben und wieder verarbeiten lassen.

    Gruß
     
  14. Tom299, 30.05.2012 #14
    Tom299

    Tom299 Android-Experte

    Beiträge:
    602
    Erhaltene Danke:
    120
    Registriert seit:
    31.08.2011
    Dann machste nen Default-Konstruktor für die anderen Klassen, die keinen Handler brauchen und einen 2. Konstruktor mit Handler:

    Code:
    public class Scripty {
    
    	public Scripty() {
    		
    	}
    	
    	public Scripty(Handler handler) {
    		
    	}
    	
    	
    }
    
    Alternativ könntest du auch eine public-Methode setHandler(Handler handler) implementieren.
     
  15. swordi, 30.05.2012 #15
    swordi

    swordi Gewerbliches Mitglied

    Beiträge:
    3,389
    Erhaltene Danke:
    441
    Registriert seit:
    09.05.2009
    wie wärs wenn du zuerst java lernen würdest.

    hier wird dir niemand eine java schulung geben, die dir weiterhilft. so macht das dann wenig sinn. die grundlagen muss man schon beherrschen, sonst wird das nichts
     
  16. Tom299, 30.05.2012 #16
    Tom299

    Tom299 Android-Experte

    Beiträge:
    602
    Erhaltene Danke:
    120
    Registriert seit:
    31.08.2011
    Code:
    10 print "Hallo"
    20 goto 10
    
    :D
     

Diese Seite empfehlen