Android HTTP Client Data Retrieval and JSON Processing Implementation

Quá trình truy xuất dữ liệu từ máy chủ HTTP trên Android yêu cầu thiết kế các thành phần mạng, xử lý JSON và cập nhật giao diện. Dưới đây là hướng dẫn chi tiết các thành phần chính.


package com.example.school.util;

import java.util.ArrayList;
import java.util.List;

public class AppConstants {
    
    public static final String SERVER_BASE = "http://192.168.1.100:8080/School/";
    public static final String API_ENDPOINT = "aclasquery";
    public static final String FULL_API_URL = SERVER_BASE + API_ENDPOINT;
    
    public static List<String> classIds = new ArrayList<>();
    public static List<String> classNames = new ArrayList<>();
    public static List<String> classDescriptions = new ArrayList<>();
    
    public static int screenWidth;
    public static int screenHeight;
    
    public static final int MSG_SUCCESS = 1;
    public static final int MSG_ERROR = 2;
    public static final int MSG_CONNECTING = 3;
    public static final int MSG_DISCONNECTED = 4;
}

Lớp Util cung cấp các phương thức hỗ trợ chuyển đổi luồng đầu vào thành chuỗi và phân tích JSON. Phương thức convertStreamToString sử dụng BufferedReader để đọc dữ liệu từ InputStream, trả về chuỗi hoàn chỉnh. Phương thức parseJsonToClassList xử lý chuỗi JSON, trích xuất các mục từ mảng 'classes' và lưu vào các danh sách tương ứng.


public static String convertStreamToString(InputStream inputStream) {
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
        StringBuilder response = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            response.append(line);
        }
        return response.toString();
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

public static void parseJsonToClassList(String jsonData) throws JSONException {
    JSONObject rootObject = new JSONObject(jsonData);
    JSONArray classesArray = rootObject.getJSONArray("classes");
    for (int i = 0; i < classesArray.length(); i++) {
        JSONObject classItem = classesArray.getJSONObject(i);
        AppConstants.classIds.add(classItem.getString("id"));
        AppConstants.classNames.add(classItem.getString("name"));
        AppConstants.classDescriptions.add(classItem.getString("description"));
    }
}

Lớp NetworkThread thực hiện kết nối HTTP và xử lý phản hồi. Phương thức fetchHttpResponse gửi yêu cầu GET đến URL, trả về InputStream. Nếu xảy ra lỗi, thông báo được gửi đến Handler để cập nhật giao diện.


public class NetworkThread extends Thread {
    
    private Message uiMessage;
    private Bundle dataBundle;
    
    @Override
    public void run() {
        InputStream responseStream = fetchHttpResponse(AppConstants.FULL_API_URL);
        if (responseStream == null) return;
        
        String jsonResponse = Util.convertStreamToString(responseStream);
        try {
            Util.parseJsonToClassList(jsonResponse);
            sendUiUpdate(AppConstants.MSG_SUCCESS, "");
        } catch (Exception e) {
            sendUiUpdate(AppConstants.MSG_ERROR, e.getMessage());
        }
    }
    
    private InputStream fetchHttpResponse(String apiUrl) {
        try {
            HttpClient httpClient = new DefaultHttpClient();
            HttpGet request = new HttpGet(apiUrl);
            HttpResponse response = httpClient.execute(request);
            return response.getEntity().getContent();
        } catch (Exception e) {
            e.printStackTrace();
            sendUiUpdate(AppConstants.MSG_ERROR, e.getMessage());
            return null;
        }
    }
    
    private void sendUiUpdate(int messageType, String messageText) {
        uiMessage = new Message();
        dataBundle = new Bundle();
        dataBundle.putString("message", messageText);
        uiMessage.what = messageType;
        uiMessage.setData(dataBundle);
        MainActivity.mainHandler.sendMessage(uiMessage);
    }
}

Class MainActivity quản lý giao diện người dùng và xử lý các sự kiện. Phương thức fetchClassData cập nhật danh sách lớp học từ các biến toàn cục. Handler mainHandler xử lý các thông báo từ NetworkThread, hiển thị thông báo lỗi hoặc cập nhật danh sách khi kết nối thành công.


public class MainActivity extends ListActivity {
    static ClassAdapter classAdapter;
    static Context context;
    static ProgressDialog progressDialog;
    static Toast toast;
    NetworkThread networkThread;
    static int dataFetchCount = 0;
    ListView listView;
    int itemId;
    ClassItemView item;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_class_list);
        context = getApplicationContext();
        getScreenDimensions();
        classAdapter = new ClassAdapter(this);
        progressDialog = ProgressDialog.show(this, "Kết nối", "Đang kết nối đến máy chủ: " + AppConstants.FULL_API_URL, true, false);
        setListAdapter(classAdapter);
        
        networkThread = new NetworkThread();
        networkThread.start();
    }
    
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        String idStr = classAdapter.getItem(position).classId.getText().toString();
        itemId = Integer.parseInt(idStr);
        super.onListItemClick(l, v, position, id);
    }
    
    public static void fetchClassData() {
        classAdapter.dataItems.clear();
        if (AppConstants.classIds.size() > 0) {
            for (int i = 0; i < AppConstants.classIds.size(); i++) {
                classAdapter.addItem(
                    AppConstants.classIds.get(i),
                    AppConstants.classNames.get(i),
                    AppConstants.classDescriptions.get(i),
                    1
                );
            }
        }
        dataFetchCount++;
    }
    
    public static Handler mainHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case AppConstants.MSG_ERROR:
                    toast = Toast.makeText(context, "Lỗi: " + msg.getData().getString("message"), Toast.LENGTH_LONG);
                    toast.show();
                    break;
                case AppConstants.MSG_SUCCESS:
                    progressDialog.dismiss();
                    fetchClassData();
                    classAdapter.notifyDataSetChanged();
                    toast = Toast.makeText(context, "Dữ liệu đã được tải thành công", Toast.LENGTH_LONG);
                    toast.show();
                    break;
            }
            super.handleMessage(msg);
        }
    };
    
    private void getScreenDimensions() {
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        AppConstants.screenWidth = size.x;
        AppConstants.screenHeight = size.y;
    }
}

Lớp ClassAdapter mở rộng BaseAdapter để quản lý danh sách lớp học. Mỗi mục trong danh sách được hiển thị thông qua lớp ClassItemView, xử lý các nút thao tác như xóa và cập nhật. Để tránh xung đột sự kiện click, các nút được cấu hình với setFocusable(false).


class ClassAdapter extends BaseAdapter {
    Context context;
    List<ClassItemView> dataItems;
    
    public ClassAdapter(Context ctx) {
        context = ctx;
        dataItems = new ArrayList<>();
    }
    
    @Override
    public int getCount() {
        return dataItems.size();
    }
    
    @Override
    public Object getItem(int position) {
        return dataItems.get(position);
    }
    
    @Override
    public long getItemId(int position) {
        return position;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ClassItemView item;
        if (convertView == null) {
            item = new ClassItemView(context, dataItems.get(position));
        } else {
            item = (ClassItemView) convertView;
            item.updateContent(dataItems.get(position));
        }
        return item;
    }
    
    public void addItem(String id, String name, String description, int type) {
        dataItems.add(new ClassItemView(context, id, name, description, type));
    }
}

class ClassItemView extends LinearLayout {
    TextView classId;
    TextView className;
    TextView classDescription;
    Button deleteButton;
    Button updateButton;
    
    public ClassItemView(Context context, String id, String name, String description, int type) {
        super(context);
        setOrientation(HORIZONTAL);
        int height = 60;
        
        classId = new TextView(context);
        classId.setText(id);
        classId.setGravity(Gravity.CENTER);
        addView(classId, new LinearLayout.LayoutParams((int)(AppConstants.screenWidth * 0.1), height));
        
        className = new TextView(context);
        className.setText(name);
        className.setGravity(Gravity.CENTER);
        addView(className, new LinearLayout.LayoutParams((int)(AppConstants.screenWidth * 0.2), height));
        
        classDescription = new TextView(context);
        classDescription.setText(description);
        classDescription.setGravity(Gravity.LEFT);
        addView(classDescription, new LinearLayout.LayoutParams((int)(AppConstants.screenWidth * 0.4), height));
        
        if (type == 0) {
            // ... (other code)
        } else {
            deleteButton = new Button(context);
            deleteButton.setText("Xóa");
            deleteButton.setFocusable(false);
            addView(deleteButton, new LinearLayout.LayoutParams((int)(AppConstants.screenWidth * 0.15), height));
            
            updateButton = new Button(context);
            updateButton.setText("Cập nhật");
            updateButton.setFocusable(false);
            addView(updateButton, new LinearLayout.LayoutParams((int)(AppConstants.screenWidth * 0.15), height));
        }
    }
}

Thẻ: android-httpclient json-parsing android-listview android-adapter

Đăng vào ngày 20 tháng 6 lúc 20:06