디버깅을 해보시면 아래와 같은 에러가 발생합니다.
android.os.NetworkOnMainThreadException
에러의 원인은 안드로이드에서는 네트위킹등 리소스가 많이 먹은 작업은 화면을 블락시기키기 때문에 메인쓰레드가 아니라 백그라운드 쓰레드에서 처리하게 되어 있습니다. 화면을 업데이트하는게 주임무인 메인쓰레드를 블락시키면 앱이 버벅거리게 됩니다. 쓰레드를 별도로 생성하지 않으면 메인쓰레드에서 처리하게 되어있기 때문에 백그라운드 쓰레드에서 해당작업을 처리해주어야 합니다. 백그라운드 쓰레드에서 처리한 후 작업완료가 되면 콜백을 받아서 처리하게 됩니다. 이걸 asynchronous(비동기) 이라고도 합니다.
코틀린은 기본적으로 Coroutine이 탑재되어 있기 때문에 이런 처리를 하는게 좀 더 간편한데, 자바는 코드가 좀 더 필요합니다.
구현방법에는 여러가지 옵션이 있는데, Volley나 Retrofit같은 라이브러리를 사용하는게 일반적이구요, 간단하게는 백그라운드 쓰레드를 지원하는 클래스를 하나 사용하면 됩니다. 아래의 클래스를 복사해서 님의 프로젝트에 붙여넣으세요.
https://github.com/c0de-wizard/android-liveData-viewModel/blob/master/app/src/main/java/com/thomaskioko/livedatademo/repository/util/AppExecutors.java
그리고 gas station데이터를 읽어오는 부분을 loadElectricGasStationLocations 메소드로 옮기세요. 그런 다음 AppExecutors를 생성해서 newtorkIO를 안에서 호출하시면 됩니다.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
loadMapData();
}
private void loadMapData() {
AppExecutors appExecutors = new AppExecutors();
appExecutors.networkIO().execute(new Runnable() {
@Override
public void run() {
loadElectricGasStationLocations();
}
});
}
private void loadElectricGasStationLocations() {
boolean initem = false, inStatNm = false, inStatId = false, inChgerId = false, inChgerType = false, inAddr = false, inLocation = false, inUserTime = false, inMethod = false, inLat = false, inLng = false, inStatUpdDt = false;
String statNm = null, statId = null, chgerId = null, chgerType = null, addr = null, location = null, userTime = null, method = null;
String lat = null, lng = null, statUpdDt = null;
try{
URL url = new URL("http://apis.data.go.kr/B552584/EvCharger/getChargerInfo?serviceKey=iifF6nWLmR%2BPgzn%2BZKQfpfbSa%2FxrnJe8cRoVMGBOYvaLg0iv2dluN%2BamznkrvFKRPIQHCZkfU4shudRWucbZag%3D%3D&numOfRows=10&pageNo=123"); //검색 URL부분
...
} catch(Exception e){
}//
}
}
한가지 주의하실 점은 map에 마커를 표시하는 코드는 다시 메인쓰레드 안에서 이루어져야 하므로 runOnUiThread를 호출하여 그 안에서 실행하셔야 합니다. 아래 링크를 참조하세요.
https://stackoverflow.com/questions/11140285/how-do-we-use-runonuithread-in-android
이런 추가 코드가 귀찮다면, Volley나 Retrofit같은 라이브러리를 사용하시면 됩니다. RxJava까지 사용하면 좀 더 구조화된 코드를 짜실 수 있구요. 그리고 아직은 힘드시겠지만, 이런 네트워크 처리 작업은 액티비티와는 무관하기 때문에, 별도의 클래스를 두어서 재사용성과 테스트를 쉽게 만들어주는게 일반적인 방식입니다. 그리고 XML 파싱하는 부분도 다시 고민해보셔서 에러처리도 추가하시고 (파싱에러, 응답데이터 에러)가독성을 높이는 방향으로 수정하시고 테스트도 추가하시면 좋을 것 같네요.