Problem mit JSON von MySQL Datenbank, und Threads

  • Antworten:11
Alexander Schäfer
  • Forum-Beiträge: 17

13.01.2013, 13:33:22 via Website

Hallo, ich hole meine Daten von einem PHP Server aus einer mysql datenbank mittels einer json datei, dazu rufe ich die seite androidproject.php auf die mir ein json objekt liefert. Im Emulator funktioniert das FAST immer einwandfrei. Auf meinem Hardware Handy nicht, dort bleibt die Liste einfach leer.
Das (meines erachtens) relevante im Code ist das hier :
1th.start();
2 fillList();
3
4
5 }
6 public void run() {
7 getData();
8 }
9
10 public void getData() {
11// Hole JSON Object und schreibe in ein List<Meal>
12 {
Das kann ja eigentlich nicht gut gehen, einen Thread zu starten und nicht zu warten bis er seine arbeit beendet hat ( die Liste zu füllen) und dann schon die direkt die Liste zu fülle ohne das der Thread fertig ist.
Aber ich weiß einfach keine bessere Lösung, bitte um Hilfe!

Hier ist mein kompletter Quellcode der Datei :
1package com.example.as_diet2;
2
3import java.io.BufferedReader;
4import java.io.InputStream;
5import java.io.InputStreamReader;
6import java.util.ArrayList;
7import java.util.Calendar;
8import java.util.GregorianCalendar;
9
10import org.apache.http.HttpEntity;
11import org.apache.http.HttpResponse;
12import org.apache.http.NameValuePair;
13import org.apache.http.client.HttpClient;
14import org.apache.http.client.entity.UrlEncodedFormEntity;
15import org.apache.http.client.methods.HttpPost;
16import org.apache.http.client.params.ClientPNames;
17import org.apache.http.client.params.CookiePolicy;
18import org.apache.http.impl.client.DefaultHttpClient;
19import org.json.JSONArray;
20import org.json.JSONException;
21import org.json.JSONObject;
22
23import android.app.Activity;
24import android.app.ListActivity;
25import android.content.Intent;
26import android.os.Bundle;
27import android.util.Log;
28import android.view.Menu;
29import android.view.View;
30import android.widget.AdapterView;
31import android.widget.AdapterView.OnItemClickListener;
32import android.widget.ArrayAdapter;
33import android.widget.ListView;
34
35public class MealDatabaseActivity extends ListActivity implements Runnable{
36
37 InputStream is;
38 ArrayList<Meal> meals = new ArrayList<Meal>();
39 JSONObject json_data;
40 GregorianCalendar cal = new GregorianCalendar();
41 Thread th=new Thread(this);
42
43 @Override
44 public void onCreate(Bundle savedInstanceState)
45 {
46 super.onCreate(savedInstanceState);
47 cal.add( Calendar.DATE, 0 );
48
49 th.start();
50 fillList();
51
52
53 }
54 public void run() {
55 getData();
56 }
57
58 public void getData()
59 {
60 Log.d("error","einmal aufgerufen");
61 String result = "";
62 ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
63
64 try{
65 HttpClient httpclient = new DefaultHttpClient();
66 //Falls der Server Cookies setzen will.
67 httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY,
68 CookiePolicy.NETSCAPE);
69 httpclient.getParams().setParameter("http.protocol.single-cookie-header", true);
70 HttpPost httppost = new HttpPost("XXX");// Der Link
71 httppost.getParams().setParameter(
72 ClientPNames.COOKIE_POLICY, CookiePolicy.NETSCAPE);
73
74 httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
75 HttpResponse response = httpclient.execute(httppost);
76 HttpEntity entity = response.getEntity();
77 is = entity.getContent();
78 }catch(Exception e){
79 Log.e("log_tag", "Fehler bei der http Verbindung "+e.toString());
80 }
81
82 try{
83 BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
84 StringBuilder sb = new StringBuilder();
85 String line = null;
86 while ((line = reader.readLine()) != null) {
87 sb.append(line + "n");
88 }
89 is.close();
90 result=sb.toString();
91 }catch(Exception e){
92 Log.e("log_tag", "Error converting result "+e.toString());
93 }
94
95 try{
96 JSONArray jArray = new JSONArray(result);
97 for(int i=0;i<jArray.length();i++){
98 json_data = jArray.getJSONObject(i);
99 Meal meal =new Meal();
100 meal.setId(json_data.getInt("id"));
101 meal.setName(json_data.getString("name"));
102 meal.setKh(json_data.getDouble("kohlenhydrate"));
103 meal.setProtein(json_data.getDouble("protein"));
104 meal.setFett(json_data.getDouble("fett"));
105 meal.setKcal(json_data.getDouble("kcal"));
106 meals.add(meal);
107
108 }
109
110
111 }
112 catch(JSONException e){
113 Log.e("log_tag", "Error parsing data "+e.toString());
114 }
115 }
116
117 public void fillList() {
118 Log.d("error","FILLIST");
119
120 this.setListAdapter(new ArrayAdapter<Meal>(this, android.R.layout.simple_list_item_1, meals));
121 }
122
123 @Override
124 public void onListItemClick(ListView l, View v, int position, long id) {
125
126 Log.d("error","MEAL NAME :"+meals.get(position).name);
127 Intent intent = new Intent(MealDatabaseActivity.this, AddMealActivity.class);
128 Meal meal= meals.get(position);
129 meal.setDay(cal.getTime().getDate());
130 meal.setMonth(cal.getTime().getMonth()+1);
131 meal.setYear(Calendar.getInstance().get(Calendar.YEAR));
132 meal.setHour(cal.getTime().getHours());
133 meal.setMinute(cal.getTime().getMinutes());
134 intent.putExtra("duwag", meal);
135 startActivity(intent);
136 }
137
138 @Override
139 public boolean onCreateOptionsMenu(Menu menu) {
140 super.onCreateOptionsMenu(menu);
141 getMenuInflater().inflate(R.menu.activity_main, menu);
142 menu.findItem(R.id.help_menu_item).setIntent(new Intent(this, HelpActivity.class));
143 menu.findItem(R.id.settings_menu_item).setIntent(new Intent(this, SettingsActivity.class));
144 return true;
145 }
146
147
148
149
150}

Antworten
Andreas Hoffmann
  • Forum-Beiträge: 36

13.01.2013, 14:07:40 via Website

Wie wäre es, wenn du am ende der run() Methode die fillList() Methode aufrufst?
Weil aber die run() nicht von dem UI Thread ausgeführt wird musst du noch die Methode runOnUiThread() aufrufen und darin fillList()...

Sieht dann so aus...

1public void run() {
2 getData();
3 MealDatabaseActivity.this.runOnUiThread(new Runnable() {
4 public void run()
5 {
6 MealDatabaseActivity.this.fillList();
7 }
8 });
9}

Musst du mal ausprobieren, aber wenn ich keinen Fehler in meinen überlegungen habe müsste das so funktionieren...

Was aus gehen könnte wäre ein th.join() (openbook.galileocomputing.de/javainsel9/javainsel_14_003.htm#mj4d4380c02798d72c9129099992a3f7c1)

1th.start();
2th.join();
3fillList();

Alexander Schäfer

Antworten
Andreas Hoffmann
  • Forum-Beiträge: 36

13.01.2013, 14:12:57 via Website

Andreas Hoffman

1th.start();
2th.join();
3fillList();

:what: Das würde zwar vllt funktionieren, jedoch fällt mir ein, dass ich dir davon abraten muss... Dadurch muss der UI Thread auf eine Antwort von Server waren und das kann dazu führen dass die Grafische Obefläche einfriert...

Also die Lösung über ein Callback müsste funtionieren

Andreas Hoffman

1public void run() {
2 getData();
3 MealDatabaseActivity.this.runOnUiThread(new Runnable() {
4 public void run()
5 {
6 MealDatabaseActivity.this.fillList();
7 }
8 });
9}

:D

Alexander Schäfer

Antworten
Alexander Schäfer
  • Forum-Beiträge: 17

13.01.2013, 14:41:22 via Website

Wow, vielen dank! das letztere hat funktioniert!
Endlich. Vielen vielen dank

Antworten
Andreas Hoffmann
  • Forum-Beiträge: 36

13.01.2013, 14:47:05 via Website

Andreas Hoffman

1public void run() {
2 getData();
3 MealDatabaseActivity.this.runOnUiThread(new Runnable() {
4 public void run()
5 {
6 MealDatabaseActivity.this.fillList();
7 }
8 });
9}

Ich hoffe du meinst das mit dem Letzten...
Freut mich wenn ich dir helfen konnte

— geändert am 13.01.2013, 14:47:21

Antworten
Alexander Schäfer
  • Forum-Beiträge: 17

13.01.2013, 15:05:17 via Website

101-13 15:02:19.365: E/AndroidRuntime(21697): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.as_diet2/com.example.as_diet2.MainActivity}: java.lang.ClassCastException: android.widget.TextView cannot be cast to android.widget.Button

Ich habe noch einen Fehler, den ich einfach nicht verstehe. Ich habe eine TextView die innerhalb eines TableLayouts ist...ziehe ich das TextFeld in ein RelativeLayout, stürzt die App ab und ich bekomme oben genannten Fehler...wieso ist das so?? wie kann ich das beheben?

die .xml Datei :
1<LinearLayout xmlns:android="XXX"
2 xmlns:tools="XXX"
3 android:id="@+id/LinearLayout1"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 android:orientation="vertical"
7 tools:context=".MainActivity" >
8
9 <RelativeLayout
10 android:layout_width="match_parent"
11 android:layout_height="wrap_content" >
12
13 <ImageView
14 android:id="@+id/pfeil1"
15 android:layout_width="wrap_content"
16 android:layout_height="wrap_content"
17 android:src="@drawable/arrow_left" />
18
19 <ImageView
20 android:id="@+id/pfeil2"
21 android:layout_width="wrap_content"
22 android:layout_height="wrap_content"
23 android:layout_alignParentRight="true"
24 android:layout_alignParentTop="true"
25 android:src="@drawable/arrow_right" />
26
27 <TextView
28 android:id="@+id/textView1"
29 android:layout_width="wrap_content"
30 android:layout_height="wrap_content"
31 android:layout_centerHorizontal="true"
32 android:layout_centerVertical="true"
33 android:text="@string/main"
34 android:textSize="26sp" />
35
36 </RelativeLayout>
37
38 <RelativeLayout
39 android:layout_width="match_parent"
40 android:layout_height="wrap_content" >
41
42 <TextView
43 android:id="@+id/kalorien"
44 android:layout_width="wrap_content"
45 android:layout_height="wrap_content"
46 android:layout_alignParentRight="true"
47 android:layout_alignParentTop="true"
48 android:layout_marginRight="10dp"
49 android:text="3000kcal"
50 android:textColor="@color/kalorien_gruen"
51 android:textSize="35sp" />
52
53 <TextView
54 android:id="@+id/main_prozent"
55 android:layout_width="wrap_content"
56 android:layout_height="wrap_content"
57 android:layout_alignParentLeft="true"
58 android:layout_alignParentTop="true"
59 android:layout_marginLeft="10dp"
60 android:text="0%"
61 android:textSize="35sp" />
62
63 </RelativeLayout>
64
65 <RelativeLayout
66 android:layout_width="match_parent"
67 android:layout_height="wrap_content" >
68
69 </RelativeLayout>
70
71 <RelativeLayout
72 android:layout_width="match_parent"
73 android:layout_height="wrap_content" >
74
75 </RelativeLayout>
76
77 <TableLayout
78 android:layout_width="match_parent"
79 android:layout_height="wrap_content"
80 android:background="@layout/shape_white" >
81
82 <TableRow
83 android:id="@+id/tableRow1"
84 android:layout_width="wrap_content"
85 android:layout_height="wrap_content"
86 android:layout_marginBottom="2dp"
87 android:background="@layout/shape"
88 android:showDividers="beginning" >
89
90 <Button
91 android:id="@+id/main_meal_button"
92 android:layout_width="wrap_content"
93 android:layout_height="wrap_content"
94 android:background="@android:color/white"
95 android:drawableLeft="@drawable/forkknife"
96 android:text="etwas Essen" />
97
98 <TextView
99 android:id="@+id/restkalorientext"
100 android:layout_width="wrap_content"
101 android:layout_height="wrap_content"
102 android:text="bereits:"
103 android:textStyle="bold" />
104
105 </TableRow>
106
107 <TableRow
108 android:id="@+id/tableRow2"
109 android:layout_width="wrap_content"
110 android:layout_height="wrap_content"
111 android:layout_marginBottom="2dp"
112 android:background="@layout/shape" >
113
114 <Button
115 android:id="@+id/main_settings_button"
116 android:layout_width="wrap_content"
117 android:layout_height="wrap_content"
118 android:background="@android:color/white"
119 android:drawableLeft="@drawable/settings"
120 android:text="Einstellungen" />
121
122 </TableRow>
123
124 <TableRow
125 android:id="@+id/tableRow3"
126 android:layout_width="wrap_content"
127 android:layout_height="wrap_content"
128 android:layout_marginBottom="2dp"
129 android:background="@layout/shape" >
130
131 <Button
132 android:id="@+id/main_help_button"
133 android:layout_width="wrap_content"
134 android:layout_height="wrap_content"
135 android:background="@android:color/white"
136 android:drawableLeft="@drawable/settings"
137 android:text="Hilfe" />
138
139 </TableRow>
140
141 <TableRow
142 android:id="@+id/tableRow4"
143 android:layout_width="wrap_content"
144 android:layout_height="wrap_content"
145 android:background="@layout/shape" >
146
147 <Button
148 android:id="@+id/main_database_button"
149 android:layout_width="wrap_content"
150 android:layout_height="wrap_content"
151 android:background="@android:color/white"
152 android:drawableLeft="@drawable/forkknife"
153 android:text="Online Datenbank" />
154
155 </TableRow>
156 </TableLayout>
157
158</LinearLayout>

Hier in der Activity wie es benutzt wird :
1TextView kalorientext=(TextView) findViewById(R.id.kalorien);
2.
3.
4 kalorientext.setText(""+df0.format(restkalorien)+"kcal");

Antworten
Andreas Hoffmann
  • Forum-Beiträge: 36

13.01.2013, 15:16:45 via Website

Für mich sieht es nach einem Bug aus...
du solltest auf jeden fall eine TextView bekommen.
von daher kann die ClassCastException nicht stimmen.
Ich glaube das Android SDK hat manchmal Probleme, wenn man in der XML rumkopiert...

Probier mal Folgedes:

  1. Alles rückgangig machen - speichern
  2. TextView aus TableLayouts ausschneiden -speichern
  3. TextView ins RelativeLayout einfügen -speichern

Aber kp ob das funktioniert

— geändert am 13.01.2013, 15:17:10

Alexander Schäfer

Antworten
San Blarnoi
  • Forum-Beiträge: 2.545

13.01.2013, 16:49:36 via Website

Ich hatte das auch schon mal -- ein clean hat geholfen.

Antworten
Alexander Schäfer
  • Forum-Beiträge: 17

13.01.2013, 18:11:14 via Website

Ich durchsuche meine List mithilfe einem TextWatcher, das funktioniert soweit auch.

Jetzt will ich das meine Liste wieder gefüllt wird, sobald nichts eingegeben wird, dies funktioniert auch..jedoch nur genau 1x..
1public void onTextChanged(CharSequence s, int start,
2 int before, int count)
3 {
4meals.clear();
5if (suchfeld.getText().toString().length()<=0||
6suchfeld.getText().toString().equals(" ")||
7suchfeld.getText().toString().equals(""))
8 {
9 meals=allmeals;
10 }
11.
12.
13.

Was stimmt mit meinem Code nicht?
Zum Beispiel habe ich ein Wort Spaghetti, gebe ich nun "S" ein, wird mir nur noch Spaghetti angezeigt. lösche ich das "S" wieder, wird wieder alles inder Liste angezeigt (so weit so gut) schreibe ich jetzt ein "S" und lösche es wieder, bleibt die Liste leer.

— geändert am 13.01.2013, 21:02:51

Antworten
Andreas Hoffmann
  • Forum-Beiträge: 36

13.01.2013, 22:17:41 via Website

Das Problem ist, dass du deine Liste leerst... Leider die Liste "allmeals"...
Ich weiß nicht, wie gut du dich mit Java und Referenzen auskennst. Ich versuche dir das zu erklären...

Vor dem ersten durchlauf hast du Zwei verschiedene Listen mit Elementen

meals => Spagetti, Spinat, Spiralnudel
allmeals => Spagetti, Spinat, Spiralnudel

Dann wird dein Code ausgeführt:

Alexander Schäfer

1public void onTextChanged(CharSequence s, int start,
2 int before, int count)
3 {
4meals.clear();
5if (suchfeld.getText().toString().length()<=0||
6suchfeld.getText().toString().equals(" ")||
7suchfeld.getText().toString().equals(""))
8 {
9 meals=allmeals;
10 }
11.
12.
13.

Was passiert? Du nimmst alle Elemente aus der Liste Meals "meals.clear();"

meals => "empty"
allmeals => Spagetti, Spinat, Spiralnudel


Dann machst du folgendes "meals=allmeals;", was dazu führt das meals = allmeals ist, also die SELBE Liste

meals = allmeals => Spagetti, Spinat, Spiralnudel

Wenn dein Code dann nochmals ausgeführ wird, auch der Befehl "meals.clear();" was dazu führ das dein Liste leer wird!

meals = allmeals => "empty"

Die Lösung ist (glaube ich) dass du "meals=allmeals;" durch "meals.addAll(allmeals);" benutzt. docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html#addAll%28int,%20java.util.Collection%29

— geändert am 13.01.2013, 22:25:41

Alexander Schäfer

Antworten
Alexander Schäfer
  • Forum-Beiträge: 17

13.01.2013, 22:25:11 via Website

Oh mann..vielen Dank! ich habe vergessen das es ja nur eine Zuweisung ist, also auf die selbe Liste zeigt..!
Daumen Hoch!

Antworten
Andreas Hoffmann
  • Forum-Beiträge: 36

13.01.2013, 22:35:17 via Website

Debuggen hilft in solchen Fällen auch oft weiter...

Antworten