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!
android java autocompletetextview json asynctask activity arrayadapter
Commentami!