BÀI 57 - SỬ DỤNG FILE JSON TRONG ANDROID
JSON Object
JSON Object
Code đọc JSON thành phố Việt Nam mà Hama chia sẻ:
Tạo 3 class để đọc JSON như sau:
JSON thành phố
@SuppressLint("StaticFieldLeak")
private class readJSONCity extends AsyncTask<String, Void, String>{
@Override
protected String doInBackground(String... strings) {
StringBuilder chuaDuLieu = new StringBuilder();
try {
URL url = new URL(strings[0]);
InputStreamReader inputStreamReader = new InputStreamReader(url.openConnection().getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
while ((line = bufferedReader.readLine()) != null){
chuaDuLieu.append(line);
}
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
return chuaDuLieu.toString();
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
JSONObject jsonObject = new JSONObject(s);
JSONArray jsonArray = jsonObject.getJSONArray("thanhpho");
arrayListNameCity.clear();
arrayListCity.clear();
for (int i=0; i<jsonArray.length(); i++){
JSONObject getData = jsonArray.getJSONObject(i);
String idCity = getData.getString("province_id");
String nameCity = getData.getString("province_name");
String typeCity = getData.getString("province_type");
arrayListCity.add(new classThanhPho(idCity, nameCity, typeCity));
arrayListNameCity.add(nameCity);
}
// showToast(arrayListNameCity.get(1));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
JSON quận huyện
@SuppressLint("StaticFieldLeak")
private class readJSONQuanHuyen extends AsyncTask<String, Void, String>{
@Override
protected String doInBackground(String... strings) {
StringBuilder dulieuQuanHuyen = new StringBuilder();
try {
URL url = new URL(strings[0]);
InputStreamReader inputStreamReader = new InputStreamReader(url.openConnection().getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
while ((line = bufferedReader.readLine()) != null){
dulieuQuanHuyen.append(line);
}
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
return dulieuQuanHuyen.toString();
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
JSONObject jsonObject = new JSONObject(s);
JSONArray jsonArray = jsonObject.getJSONArray("quanhuyen");
for (int i=0; i<jsonArray.length(); i++){
JSONObject getData = jsonArray.getJSONObject(i);
String idCity = getData.getString("province_id");
String idquanhuyen, tenquanhuyen;
if (idCity.equals(idthanhpho)){
idquanhuyen = getData.getString("district_id");
tenquanhuyen = getData.getString("district_name");
arrayListQuanHuyen.add(new classQuanHuyen(idCity, idquanhuyen, tenquanhuyen));
arrayNameQuanHuyen.add(tenquanhuyen);
}
}
// showToast(arrayNameQuanHuyen.get(4));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
JSON xã phường
@SuppressLint("StaticFieldLeak")
private class readJSONXaPhuong extends AsyncTask<String, Void, String>{
@Override
protected String doInBackground(String... strings) {
StringBuilder dataXaPhuong = new StringBuilder();
try {
URL url = new URL(strings[0]);
InputStreamReader inputStreamReader = new InputStreamReader(url.openConnection().getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
while ((line = bufferedReader.readLine()) != null){
dataXaPhuong.append(line);
}
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
return dataXaPhuong.toString();
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
JSONObject jsonObject = new JSONObject(s);
JSONArray jsonArray = jsonObject.getJSONArray("xaphuong");
for (int i=0; i<jsonArray.length(); i++){
JSONObject getData = jsonArray.getJSONObject(i);
String idQH = getData.getString("district_id");
String idXaPhuong, tenXaPhuong;
if (idQH.equals(idQuanHuyen)){
idXaPhuong = getData.getString("ward_id");
tenXaPhuong = getData.getString("ward_name");
arrayListXaPhuong.add(new classXaPhuong(idthanhpho, idQuanHuyen, idXaPhuong, tenXaPhuong));
arrayNameXaPhuong.add(tenXaPhuong);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Để sử dụng trước tiên gọi hàm đếm ngược thời gian để load dữ liệu trước khi cho người dùng sử dụng
new CountDownTimer(2000,1000){
@Override
public void onTick(long millisUntilFinished) {
new readJSONCity().execute("https://robotquantrac.web.app/thanhpho.json"); // Bắt đầu nhào vô đọc nè
}
@Override
public void onFinish() {
actionCity(); // Bắt sự kiện người dùng nhập tên thành phố
}
}.start();
Tạo các biến toàn cục sau:
String thanhPho, quanHuyen, xaPhuong;
public static ArrayList<classThanhPho> arrayListCity;
public static ArrayList<classQuanHuyen> arrayListQuanHuyen;
public static ArrayList<classXaPhuong> arrayListXaPhuong;
ArrayList<String> arrayListNameCity;
ArrayList<String> arrayNameQuanHuyen;
ArrayList<String> arrayNameXaPhuong;
Object[] mangthanhpho;
String idthanhpho, idQuanHuyen;
boolean findQuanHuyen = false, findXaPhuong = false;
int bamQuanHuyen = 0, bamXaPhuong = 0;
Mình sử dụng autocomplete textView cho editText nhập thành phố nên mình sẽ đổ toàn bộ tên thành phố vào mảng và truyền cho editText. Khi người dùng nhập tên tương ứng editText sẽ hiển thị tên tương ứng.
Ngoài ra, nếu người dùng cố ý hoặc vô tình nhập sai tên thì sẽ trả về lỗi nhập tào lao. Hoặc khi không tìm thấy tên tỉnh nào giống trong dữ liệu cũng sẽ thông báo tỉnh không tồn tại.
Dưới đây là code để đổ dữ liệu cho editText thành phố.
mangthanhpho = arrayListNameCity.toArray();
ArrayAdapter<Object> arrayAdapter = new ArrayAdapter<>(this
, support_simple_spinner_dropdown_item ,mangthanhpho);
edtThanhPho.setAdapter(arrayAdapter);
Khi có tên thành phố rồi, người dùng sẽ nhập tên quận huyện. Nếu người dùng cố tình bỏ qua mà nhập xã phường thì cũng sẽ báo chưa nhập quận huyện.
Thuật toán của mình là sẽ lấy tên thành phố vừa nhập đem so sánh với mảng thành phố chứa thông tin tên thành phố và id của thành phố đó. Nếu kết quả so sánh tên trùng khớp thì sẽ lưu id của thành phố lại.
Chuyển qua một vòng lặp for khác để quét toàn bộ quận huyện trong JSON lọc ra các quận huyện có id trùng khớp. Xã phường mình cũng làm tương tự vậy. Cách này nhược điểm là người dùng phải có mạng internet.
Dưới đây là code cho quận huyện.
edtQuanHuyen.setOnClickListener(v -> {
boolean daNhapQuanHuyen = false;
bamQuanHuyen++;
thanhPho = edtThanhPho.getText().toString();
if (bamQuanHuyen == 1) {
if (thanhPho.isEmpty()) {
tilThanhPho.setError(getString(R.string.nhap_thanh_pho_da));
tilQuanHuyen.setError(null);
edtQuanHuyen.setText(null);
findQuanHuyen = false;
} else {
tilThanhPho.setError(null);
daNhapQuanHuyen = true;
for (int i = 0; i < arrayListCity.size(); i++) {
if (thanhPho.equals(arrayListCity.get(i).getNameCity())) {
idthanhpho = arrayListCity.get(i).getIdCity();
findQuanHuyen = true;
new readJSONQuanHuyen().execute("https://robotquantrac.web.app/quanhuyen.json");
break;
}
}
}
}
if (findQuanHuyen){
tilThanhPho.setError(null);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this
, support_simple_spinner_dropdown_item, arrayNameQuanHuyen);
arrayAdapter.notifyDataSetChanged();
edtQuanHuyen.setAdapter(arrayAdapter);
} else {
if (daNhapQuanHuyen){
tilThanhPho.setError(getString(R.string.ten_thanh_pho_sai));
}
}
});
Dưới đây là code xã phường.
edtXaPhuong.setOnClickListener(v -> {
bamXaPhuong++;
thanhPho = edtThanhPho.getText().toString();
quanHuyen = edtQuanHuyen.getText().toString();
if (bamXaPhuong == 1) {
if (thanhPho.isEmpty()) {
tilThanhPho.setError(getString(R.string.nhap_thanh_pho_da));
tilXaPhuong.setError(null);
tilQuanHuyen.setError(null);
edtXaPhuong.setText(null);
findXaPhuong = false;
} else if (quanHuyen.isEmpty()) {
tilQuanHuyen.setError(getString(R.string.nhap_quan_huyen_da));
tilThanhPho.setError(null);
tilXaPhuong.setError(null);
edtXaPhuong.setText(null);
findXaPhuong = false;
} else {
tilThanhPho.setError(null);
tilQuanHuyen.setError(null);
tilXaPhuong.setError(null);
for (int i = 0; i < arrayListQuanHuyen.size(); i++) {
if (quanHuyen.equals(arrayListQuanHuyen.get(i).getTenQuanHuyen())) {
idQuanHuyen = arrayListQuanHuyen.get(i).getIdQuanHuyen();
findXaPhuong = true;
new readJSONXaPhuong().execute("https://robotquantrac.web.app/xaphuong.json");
break;
}
}
}
}
if (findXaPhuong){
tilQuanHuyen.setError(null);
tilThanhPho.setError(null);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(xacNhanMuaHangActivity.this,
support_simple_spinner_dropdown_item, arrayNameXaPhuong);
arrayAdapter.notifyDataSetChanged();
edtXaPhuong.setAdapter(arrayAdapter);
}
});
Khi người dùng cố tình thay đổi địa điểm khác thì code sẽ reset tương ứng như sau:
edtThanhPho.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
bamQuanHuyen = 0;
bamXaPhuong = 0;
arrayNameXaPhuong.clear();
arrayListXaPhuong.clear();
arrayNameQuanHuyen.clear();
arrayListQuanHuyen.clear();
edtQuanHuyen.setText(null);
edtXaPhuong.setText(null);
}
@Override
public void afterTextChanged(Editable s) {
bamQuanHuyen = 0;
bamXaPhuong = 0;
arrayNameXaPhuong.clear();
arrayListXaPhuong.clear();
arrayNameQuanHuyen.clear();
arrayListQuanHuyen.clear();
edtQuanHuyen.setText(null);
edtXaPhuong.setText(null);
}
});
edtQuanHuyen.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
bamXaPhuong = 0;
arrayNameXaPhuong.clear();
arrayListXaPhuong.clear();
edtXaPhuong.setText(null);
}
@Override
public void afterTextChanged(Editable s) {
bamXaPhuong = 0;
arrayNameXaPhuong.clear();
arrayListXaPhuong.clear();
edtXaPhuong.setText(null);
}
});