AutoCompleteTextView da JSON in Android

Mattepuffo's logo
AutoCompleteTextView da JSON in Android

AutoCompleteTextView da JSON in Android

AutoCompleteTextView è un componente che in pratica si comporta come Google Suggest.

Oggi vediamo come usarlo, e per complicarci la vita, prenderemo in dati in formato JSON da un servizio remoto, e useremo un custom adapter.

Cominciamo con la classe che mappa i dati JSON:

public class Cities {

    private int id;
    private String nome;
    private String paese;
    private double latitudine;
    private double longitudine;

    public Cities(int id, String nome) {
        this.id = id;
        this.nome = nome;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getPaese() {
        return paese;
    }

    public void setPaese(String paese) {
        this.paese = paese;
    }

    public double getLatitudine() {
        return latitudine;
    }

    public void setLatitudine(double latitudine) {
        this.latitudine = latitudine;
    }

    public double getLongitudine() {
        return longitudine;
    }

    public void setLongitudine(double longitudine) {
        this.longitudine = longitudine;
    }

}

I i campi JSON quindi sono:

  • id
  • nome
  • paese
  • latitudine
  • longitudine

Il passo successivo è la classe che recupera i dati; anche se proprio non correttissimo, da un punto di vista di "stile", ci ho messo anche il parsing:

public class JsonParse {

    public static List getCities(String city) throws IOException, JSONException {
        List list = new ArrayList();
        String temp = city.replace(" ", "%20");
        URL url = new URL("http://www.sito.com/service.php?nome=" + temp);
        URLConnection uc = url.openConnection();
        BufferedReader buf = new BufferedReader(new InputStreamReader(uc.getInputStream(), "UTF-8"));
        String json = buf.readLine();
        JSONArray ja = new JSONArray(json);
        for (int i = 0; i < ja.length(); i++) {
            JSONObject obj = ja.getJSONObject(i);
            list.add(new Cities(obj.getInt("id"), obj.getString("nome")));
        }
        return list;
    }
}

In pratica, il file PHP, interroga il database prendendo come parametro ciò che scriviamo nell'AutoCompleteTextView.

Poi interpretiamo la stringa JSON e riempiamo una lista.

Il passo successivo sarà il nostro adapter:

public class JsonAdapter extends ArrayAdapter {

    private Context context;
    private List items;
    private int viewResourceId;
    private static LayoutInflater inflater = null;

    public JsonAdapter(Context context, int viewResourceId, List items) {
        super(context, viewResourceId, items);
        this.context = context;
        this.items = items;
        this.viewResourceId = viewResourceId;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        if (v == null) {
            v = inflater.inflate(viewResourceId, null);
        }
        Cities cities = items.get(position);
        if (cities != null) {
            TextView txtId = (TextView) v.findViewById(R.id.city_id);
            TextView txtName = (TextView) v.findViewById(R.id.city_name);
            txtId.setText(String.valueOf(cities.getId()));
            txtName.setText(cities.getNome());
        }
        return v;
    }

    @Override
    public void notifyDataSetChanged() {
        super.notifyDataSetChanged();
    }

}

Estende ArrayAdapter, e viene "tipizzato" con la nostra classe che abbiamo visto all'inizio.

L'ultima classe che vediamo corrisponde alla nostra Activity:

public class MainActivity extends Activity {

    private AutoCompleteTextView acTextView;
    private JsonAdapter adapter;
    private List list;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        list = new ArrayList();
        acTextView = (AutoCompleteTextView) findViewById(R.id.auto_complete);
        acTextView.addTextChangedListener(new TextWatcher() {

            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            public void onTextChanged(CharSequence s, int start, int before, int count) {
                String search = s.toString();
                new GetJsonTask().execute(search);
            }

            public void afterTextChanged(Editable s) {
            }
        });
    }

    private class GetJsonTask extends AsyncTask<String, String, String> {

        @Override
        protected String doInBackground(String... params) {
            String s = params[0];
            if (s.length() > 2) {
                try {
                    list = JsonParse.getCities(s);
                    return null;
                } catch (IOException ex) {
                } catch (JSONException ex) {
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            adapter = new JsonAdapter(getApplicationContext(), R.layout.items, list);
            acTextView.setAdapter(adapter);
            adapter.notifyDataSetChanged();
        }
    }
}

Quando scriviamo, eseguiamo un AsyncTask per interrogare il servizio remoto (solo se abbiamo scritto almeno due caratteri, nel mio caso).

Nell'AsyncTask riempiamo la lista, e nel onPostExecute, settiamo l'adapter.

A questo punto ci mancano solo i layout.

Questo quello generico dell'Activity (main.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context=".MainActivity">
 
    <AutoCompleteTextView
        android:id="@+id/auto_complete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <requestFocus />
    </AutoCompleteTextView>
    
</RelativeLayout>

E questo invece quello che rappresenta le varie righe identificate (items.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical"
              android:paddingBottom="6dip"
              android:paddingLeft="5dp"
              android:paddingTop="4dip"
              android:id="@+id/linear_layout_items">

    <TextView
        android:id="@+id/city_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:visibility="gone" />
    
    <TextView
        android:id="@+id/city_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="14sp" />

</LinearLayout>

Ricordatevi di aggiungere questi permessi al manifest:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

E il gioco è fatto!

Enjoy!


Condividi

Commentami!