# Android Studio MySql Daten in Listview mit sub Item



## schnibli (16. Mrz 2015)

Hallo zusammen,

Wie im Titel angetönt, suche ich eine Lösung Daten aus einer Mysql Datenbank über PHP in ein Listview zu bringen.

Spezifikationen der App:
- Navigation mit Fragment

Mein Bisheriger Code

```
package meinapp.com.meinapp;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Roger on 11.03.2015.
 */
public class menu4_Fragment extends Fragment {
    View rootview;
    private String jsonResult;
    private String url = "http://link.zu.php.datei/config.php";
    private ListView listView;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootview = inflater.inflate(R.layout.menu4_layout, container, false);

        final ListView listview = (ListView) rootview.findViewById(R.id.listView1);
        accessWebService();
        return rootview;
    }




    // Async Task to access the web
    private class JsonReadTask extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... params) {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(params[0]);
            try {
                HttpResponse response = httpclient.execute(httppost);
                jsonResult = inputStreamToString(
                        response.getEntity().getContent()).toString();
            }

            catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        private StringBuilder inputStreamToString(InputStream is) {
            String rLine = "";
            StringBuilder answer = new StringBuilder();
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));

            try {
                while ((rLine = rd.readLine()) != null) {
                    answer.append(rLine);
                }
            }

            catch (IOException e) {
                // e.printStackTrace();

            }
            return answer;
        }

        @Override
        protected void onPostExecute(String result) {
            ListDrwaer();
        }
    }// end async task

    public void accessWebService() {
        JsonReadTask task = new JsonReadTask();
        // passes values for the urls string array
        task.execute(new String[] { url });
    }

    // build hash set for list view
    public void ListDrwaer() {
        List<Map<String, String>> employeeList = new ArrayList<Map<String, String>>();

        try {
            JSONObject jsonResponse = new JSONObject(jsonResult);
            JSONArray jsonMainNode = jsonResponse.optJSONArray("emp_info");

            for (int i = 0; i < jsonMainNode.length(); i++) {
                JSONObject jsonChildNode = jsonMainNode.getJSONObject(i);
                String name = jsonChildNode.optString("employee name");
                String number = jsonChildNode.optString("employee no");
                String outPut = name + "-" + number;
                employeeList.add(createEmployee("employees", outPut));
            }
        } catch (JSONException e) {

        }

        mSchedule = new SimpleAdapter(getActivity(), mylist, R.layout., employeeList,
                android.R.layout.simple_list_item_1,
                new String[] { "employees" }, new int[] { android.R.id.text1 });
        listView.setAdapter(simpleAdapter);
    }

    private HashMap<String, String> createEmployee(String name, String number) {
        HashMap<String, String> employeeNameNo = new HashMap<String, String>();
        employeeNameNo.put(name, number);
        return employeeNameNo;
    }

}
```

Jedoch unterstreicht er folgende Code abschnitte:

```
mSchedule = new SimpleAdapter(getActivity(), mylist, R.layout., employeeList,
                android.R.layout.simple_list_item_1,
                new String[] { "employees" }, new int[] { android.R.id.text1 });
        listView.setAdapter(simpleAdapter);
```

Kann mir jemand Helfen?


----------



## dzim (16. Mrz 2015)

*listView.setAdapter(simpleAdapter);* --> *listView.setAdapter(mSchedule);*

_mSchedule_ wurde nicht definiert (via *private SimpleAdapter mSchedule;*)

Methodennamen werden immer mit kleinen Buchstaben beginnen _ListDrwaer() --> listDrwaer() --> listDrawer()_ und in der Regel eine Aktion beschreiben: _listDrawer() --> initListDrawer()_ oder so ähnlich.

Auch würde ich das JSON-Object schon im AsyncTask erstellen - und am besten das parsen auch (deine gesamte Operation passiert auf dem UI-Thread - nicht praktisch!).

Logge eventuelle Exceptions, z.B.:

```
} catch (JSONException e) {
                android.util.Log.e(Menu4Fragment.class.getSimpleName(), "something happend", e);
        }
```

Auch werden Klassennamen stets CamelCase geschrieben:
_menu4_Fragment --> Menu4Fragment_

Darüber hinaus finde ich deinen Stil, den AsycTask zu implementieren reichlich abstrus. Kann es sein, dass du generell noch nicht so lange in Java unterwegs bist?


----------



## schnibli (16. Mrz 2015)

Unglaublich wie schnell man einen "NOOB" identifiziert. xD

Ich Arbeie erst seit ein par "Wochend" mit Java.
Vieles hat schon Funktioniert ("SSH Verbindung") oder auch einen ("TCP Clienten")

Jedoch stehe ich bei MySql auf dem Schlauch.


Kannst du mir da ev. genaueres Weiterhelfen sodass ich mal sehe wie das aussehen soll :s ? 
Ich habe schon viel gelesen und auch versucht jedoch nicht mit den Fragmenten. 

Vielen Dank für die Bemühung.


----------



## dzim (16. Mrz 2015)

Naja, ich hab das mit dem "Noob"-identifizieren ja nicht bös' gemeint. Jeder fängt an Noob an. Es gibt nur einige, die sind lernresistenter, oder besser: beratungsresistenter, als andere :-D

Du nutzt PHP ja nur als JSON-Produzenten, nicht war? Ich denke also, das der MySQL-Teil damit für dich erst einmal irrelevant ist.

Ich könnte jetzt deinen Code jetzt schon "pretty print"en, aber eigentlich habe ich dafür gerade nicht so viel Zeit. Versuche ihn nur so zu gestalten, dass du dich an Styl Guides hälst (alle Code Conventions findest du in erschöpfendem Umfang hier). Gut ist vielleicht auch der Google-Style-Guid für Java:
https://google-styleguide.googlecode.com/svn/trunk/javaguide.html

Was deinen AsyncTask jetzt angeht: Was mich stört ist, dass es im "Fluss" des Textes schwierig bis unmöglich ist sofort zu erkennen, welche Variable zu welcher Klasse (der AsyncTask ist ja eine innere Klasse) gehört.
Ich zum Beispiel ordne auch meine Haupt-Klasse immer so, das innere Klassen - wenn sie denn nötig sind - am Ende stehen. Versuche mit Klassenvariablen zu arbeiten und Getter- und Setter-Methoden zu verwenden.


----------



## schnibli (16. Mrz 2015)

Ich habe "Noob" auch nicht als Beleidigung angeschaut, habe auch bei html / php und bei vb.net einmal als "Noob" angefangen  ....
Ich denke das wird schon gut kommen bin gerade Vieles am lesen, falls ich fragen hätte, würde ich diesen Beitrag noch einmal Editieren 

Danke


----------



## schnibli (17. Mrz 2015)

So, hab mich nochmals beschäftigt und viel Gelesen "gerlernt".

Nun habe ich JSONParser ausgelagert und ein bisschen Struktur reingebracht (hoffe ich natürlich) .
Jedoch noch ein Par Unklarheiten:

```
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * Created by Roger on 11.03.2015.
 */
public class menu4_Fragment extends Fragment {
    View rootview;

    ListView list;
    TextView ver;
    TextView name;
    TextView api;
    Button Btngetdata;
    ArrayList<HashMap<String, String>> oslist = new ArrayList<HashMap<String, String>>();
    //URL to get JSON Array
    private static String url = "Linkzurdblink";
    //JSON Node Names
    private static final String TAG_OS = "android";
    private static final String TAG_VER = "ver";
    private static final String TAG_NAME = "name";
    private static final String TAG_API = "api";
    JSONArray android = null;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootview = inflater.inflate(R.layout.menu4_layout, container, false);
        final ListView listview = (ListView) rootview.findViewById(R.id.listView1);


        oslist = new ArrayList<HashMap<String, String>>();
        Btngetdata = (Button) rootview.findViewById(R.id.getdata);
        Btngetdata.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new JSONParse().execute();
            }
        });
    }
    private class JSONParse extends AsyncTask<String, String, JSONObject> {
        private ProgressDialog pDialog;
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            ver = (TextView)rootview.findViewById(R.id.vers);
            name = (TextView)rootview.findViewById(R.id.name);
            api = (TextView)rootview.findViewById(R.id.api);
            pDialog = new ProgressDialog(MainActivity.this);
            pDialog.setMessage("Getting Data ...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }
        @Override
        protected JSONObject doInBackground(String... args) {
            JSONParser jParser = new JSONParser();
            // Getting JSON from URL
            JSONObject json = jParser.getJSONFromUrl(url);
            return json;
        }
        @Override
        protected void onPostExecute(JSONObject json) {
            pDialog.dismiss();
            try {
                // Getting JSON Array from URL
                android = json.getJSONArray(TAG_OS);
                for(int i = 0; i < android.length(); i++){
                    JSONObject c = android.getJSONObject(i);
                    // Storing  JSON item in a Variable
                    String ver = c.getString(TAG_VER);
                    String name = c.getString(TAG_NAME);
                    String api = c.getString(TAG_API);
                    // Adding value HashMap key => value
                    HashMap<String, String> map = new HashMap<String, String>();
                    map.put(TAG_VER, ver);
                    map.put(TAG_NAME, name);
                    map.put(TAG_API, api);
                    oslist.add(map);
                    list=(ListView)rootview.findViewById(R.id.list);
                    ListAdapter adapter = new SimpleAdapter(MainActivity.this, oslist,
                            R.layout.list_v,
                            new String[] { TAG_VER,TAG_NAME, TAG_API }, new int[] {
                            R.id.vers,R.id.name, R.id.api});
                    list.setAdapter(adapter);
                    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> parent, View view,
                                                int position, long id) {
                            Toast.makeText(MainActivity.this, "You Clicked at "+oslist.get(+position).get("name"), Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
}
```

Nun Folgende Zeilen besitzen Fehler die ich nicht lösen kann:

```
pDialog = new ProgressDialog(menu4_Fragment.this);
ListAdapter adapter = new SimpleAdapter(MainActivity.this, oslist,

 Toast.makeText(MainActivity.this, "You Clicked at "+oslist.get(+position).get("name"), Toast.LENGTH_SHORT).show();
```

Ich nehme an das dies durch die "Fragmente entsetht".


----------



## dzim (17. Mrz 2015)

Der String ist falsch.

```
"You Clicked at "+oslist.get(+position).get("name")
```
-->

```
"You Clicked at " + oslist.get(position).get("name")
```
Oder wolltest du einfach nur eine Posittion "weiterrutschen"? Dann ist es aber immer noch *position + 1*

Was mich da nur wundert: Mit welcher IDE arbeitest du? Doch sicher Android Studio - selbst diese IDE müsste dir doch ein paar Warnings um die Ohren schmeissen, oder?


----------



## schnibli (17. Mrz 2015)

Genau die Warnings spreche ich an, die handelt von MainActivity.this. Wenn ich dies ersetze durch menu4_Fragment ersetzte, wird dies immer noch angestrichen. "is not an enclosing class"


----------



## schnibli (18. Mrz 2015)

Ich habe es entlich geschafft  

```
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * Created by Roger on 11.03.2015.
 */
public class menu4_Fragment extends Fragment {
    View rootview;

    ListView list;
    TextView ver;
    TextView name;
    TextView api;
    Button Btngetdata;
    ArrayList<HashMap<String, String>> oslist = new ArrayList<HashMap<String, String>>();
    //URL to get JSON Array
    private static String url = "http://api.learn2crack.com/android/jsonos/";
    //JSON Node Names
    private static final String TAG_OS = "android";
    private static final String TAG_VER = "ver";
    private static final String TAG_NAME = "name";
    private static final String TAG_API = "api";
    JSONArray android = null;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootview = inflater.inflate(R.layout.menu4_layout, container, false);
        final ListView listview = (ListView) rootview.findViewById(R.id.listView1);


        oslist = new ArrayList<HashMap<String, String>>();
        Btngetdata = (Button) rootview.findViewById(R.id.getdata);
        Btngetdata.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new JSONParse().execute();
            }
        });
        return rootview;
    }


    private class JSONParse extends AsyncTask<String,  String,  JSONObject> {
        private ProgressDialog pDialog;
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            ver = (TextView)rootview.findViewById(R.id.vers);
            name = (TextView)rootview.findViewById(R.id.name);
            api = (TextView)rootview.findViewById(R.id.api);
            pDialog = new ProgressDialog(getActivity());
            pDialog.setMessage("Getting Data ...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }
        @Override
        protected JSONObject doInBackground(String... args) {
            JSONParser jParser = new JSONParser();
            // Getting JSON from URL
            JSONObject json = jParser.getJSONFromUrl(url);
            return json;
        }

        @Override
        protected void onPostExecute(JSONObject json) {
            pDialog.dismiss();
            try {
                // Getting JSON Array from URL
                android = json.getJSONArray(TAG_OS);
                for(int i = 0; i < android.length(); i++){
                    JSONObject c = android.getJSONObject(i);
                    // Storing  JSON item in a Variable
                    String ver = c.getString(TAG_VER);
                    String name = c.getString(TAG_NAME);
                    String api = c.getString(TAG_API);
                    // Adding value HashMap key => value
                    HashMap<String, String> map = new HashMap<String, String>();
                    map.put(TAG_VER, ver);
                    map.put(TAG_NAME, name);
                    map.put(TAG_API, api);
                    oslist.add(map);
                    list=(ListView)rootview.findViewById(R.id.listView1);
                    ListAdapter adapter = new SimpleAdapter(getActivity(), oslist,
                            R.layout.list_v,
                            new String[] { TAG_VER,TAG_NAME, TAG_API }, new int[] {
                            R.id.vers,R.id.name, R.id.api});
                    list.setAdapter(adapter);
                    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> parent, View view,
                                                int position, long id) {
                            Toast.makeText(getActivity(), "You Clicked at " + oslist.get(position).get("name"), Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
}
```


----------



## schnibli (18. Mrz 2015)

Nun nur noch etwas kleines.
Ich würde gerne einen "Filter bez. eine Suchtextbox einfügen".
Wie kann ich das Listview Element mit einer Edittext-box filter? :s


----------



## schnibli (18. Mrz 2015)

Leider kann ich mein Beitrag nicht Editieren.

Ich bin auf folgende "Lösung" gekommen:

```
private ArrayAdapter simpleAdapter;
oslist = new ArrayList<HashMap<String, String>>();
        inputSearch.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
                // When user changed the Text
                menu4_Fragment.this.simpleAdapter.getFilter().filter(cs);
            }

            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                                          int arg3) {
                // TODO Auto-generated method stub

            }

            @Override
            public void afterTextChanged(Editable arg0) {
                // TODO Auto-generated method stub                          
            }
        });
```

Nun ist das Problem dass, das Programm stürzt ab sobald ich den Text ändere


----------



## dzim (31. Mrz 2015)

Was ist die Exception? ... Ach vergiss es: Ich denke, das hatten wir wohl schon mal: simpleAdapter ist garantiert noch nicht initialisiert!

Ich arbeite bei grösseren Datenmengen eher mit dem *ListFragment*, dass dann noch einen  *LoaderManager.LoadderCallbacks<Cursor>* implementiert. Dort tausche ich dann den Cursor aus (Filtere also, indem ich eine passende DB-Operation durchführe - ist das gut? kA, aber bei mir performt es auch bei 10000 Items immer noch sehr gut...)
Generell musst du aber auch schauen, ob dein ArrayAdapter auch die entsprechenden Methode implementiert/überschreibt, die für das Filtern am Ende zuständig sind, sonst passiert wahrscheinlich einfach nichts.


----------

