Статьи

Android AsyncTask ListView — JSON

Много раз нам нужно заполнить Listview, используя AsyncTask . Это тот случай, когда нам нужно вызвать удаленный сервер и обмениваться информацией, используя JSON .

В этом посте я хочу углубиться в анализ ListView . В предыдущих постах я описал, как использовать ListView несколькими способами с использованием стандартных и пользовательских адаптеров . Во всем примере я должен был установить фиксированные элементы. В этом посте я опишу, как можно получить элементы непосредственно с сервера JEE.

Для простоты предположим, что у нас есть простой JEE-сервер, который управляет некоторыми контактами. Наш контакт осуществляется по: имени, фамилии, электронной почте и номеру телефона. Как сделать этот сервер выходит за рамки этого поста, и я просто сделаю доступным исходный код. Просто чтобы дать вам некоторые подробности, я могу сказать, что сервер является сервером JEE, разработанным с использованием веб-сервисов RESTFul (в нашем случае — jersey api).

В этом случае приложение ведет себя как клиент, который вызывает службу удаления, чтобы получить список контактов и показать его с помощью ListView. Данные, передаваемые с сервера клиенту, форматируются с использованием JSON.

Как всегда, мы начинаем создавать наш собственный адаптер, который использует собственный макет. Если вам нужна дополнительная информация о создании собственного адаптера, вы можете посмотреть здесь и здесь . Вот код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public class SimpleAdapter extends ArrayAdapter<Contact> {
 
    private List<Contact> itemList;
    private Context context;
 
    public SimpleAdapter(List<Contact> itemList, Context ctx) {
        super(ctx, android.R.layout.simple_list_item_1, itemList);
        this.itemList = itemList;
        this.context = ctx;       
    }
 
    public int getCount() {
        if (itemList != null)
            return itemList.size();
        return 0;
    }
 
    public Contact getItem(int position) {
        if (itemList != null)
            return itemList.get(position);
        return null;
    }
 
    public long getItemId(int position) {
        if (itemList != null)
            return itemList.get(position).hashCode();
        return 0;
    }
 
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
 
        View v = convertView;
        if (v == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(R.layout.list_item, null);
        }
 
        Contact c = itemList.get(position);
        TextView text = (TextView) v.findViewById(R.id.name);
        text.setText(c.getName());
 
        TextView text1 = (TextView) v.findViewById(R.id.surname);
        text1.setText(c.getSurname());
 
        TextView text2 = (TextView) v.findViewById(R.id.email);
        text2.setText(c.getEmail());
 
        TextView text3 = (TextView) v.findViewById(R.id.phone);
        text3.setText(c.getPhoneNum());
 
        return v;
 
    }
 
    public List<Contact> getItemList() {
        return itemList;
    }
 
    public void setItemList(List<Contact> itemList) {
        this.itemList = itemList;
    }
 
}

К настоящему времени все гладко и просто.

HTTP-клиент

Единственное, что нам нужно сделать, — это создать наш HTTP-клиент, чтобы отправить запрос на сервер JEE. Как мы все знаем, HTTP-запрос может потребовать много времени, прежде чем ответ будет доступен, поэтому мы должны принять это во внимание, чтобы ОС Android не остановила наше приложение. Самое простое, что можно сделать — создать AsyncTask, который выполняет этот запрос и ожидает ответа.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
private class AsyncListViewLoader extends AsyncTask<String, Void, List<Contact>> {
    private final ProgressDialog dialog = new ProgressDialog(MainActivity.this);
 
    @Override
    protected void onPostExecute(List<Contact> result) {           
        super.onPostExecute(result);
        dialog.dismiss();
        adpt.setItemList(result);
        adpt.notifyDataSetChanged();
    }
 
    @Override
    protected void onPreExecute() {       
        super.onPreExecute();
        dialog.setMessage("Downloading contacts...");
        dialog.show();           
    }
 
    @Override
    protected List<Contact> doInBackground(String... params) {
        List<Contact> result = new ArrayList<Contact>();
 
        try {
            URL u = new URL(params[0]);
 
            HttpURLConnection conn = (HttpURLConnection) u.openConnection();
            conn.setRequestMethod("GET");
 
            conn.connect();
            InputStream is = conn.getInputStream();
 
            // Read the stream
            byte[] b = new byte[1024];
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
 
            while ( is.read(b) != -1)
                baos.write(b);
 
            String JSONResp = new String(baos.toByteArray());
 
            JSONArray arr = new JSONArray(JSONResp);
            for (int i=0; i < arr.length(); i++) {
                result.add(convertContact(arr.getJSONObject(i)));
            }
 
            return result;
        }
        catch(Throwable t) {
            t.printStackTrace();
        }
        return null;
    }
 
    private Contact convertContact(JSONObject obj) throws JSONException {
        String name = obj.getString("name");
        String surname = obj.getString("surname");
        String email = obj.getString("email");
        String phoneNum = obj.getString("phoneNum");
 
        return new Contact(name, surname, email, phoneNum);
    }
 
}

Давайте проанализируем код.

На начальном этапе ( onPreExecute () ) перед запуском задачи мы просто показываем диалоговое окно, информирующее пользователя о том, что приложение загружает список контактов. Наиболее интересной частью является метод doInBackground, где приложение устанавливает HTTP-соединение. Сначала мы создаем HTTPConnection и устанавливаем метод GET следующим образом:

1
2
3
4
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setRequestMethod("GET");
 
conn.connect();

Затем мы создаем поток ввода и затем читаем поток байтов:

1
2
3
4
5
6
InputStream is = conn.getInputStream();
 // Read the stream
 byte[] b = new byte[1024];
 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 while ( is.read(b) != -1)
    baos.write(b);

Теперь у нас есть весь поток в нашем байтовом массиве, и нам нужно просто проанализировать его с помощью JSON.

1
2
3
4
5
6
JSONArray arr = new JSONArray(JSONResp);
for (int i=0; i < arr.length(); i++) {
    result.add(convertContact(arr.getJSONObject(i)));
}
 
return result;

Готово! Что дальше?… Что ж, нам нужно сообщить адаптеру, что у нас есть новый список контактов, и он должен показать его. Мы можем сделать это в onPostExecute (результат List <Contact>), где:

1
2
3
4
super.onPostExecute(result);
dialog.dismiss();
adpt.setItemList(result);
adpt.notifyDataSetChanged();

Ссылка: Android AsyncTask ListView — JSON от нашего партнера JCG Франческо Аццолы в блоге Surviving с Android