https://github.com/leeugun123/find_gas_station
GitHub - leeugun123/find_gas_station: find_gas
find_gas. Contribute to leeugun123/find_gas_station development by creating an account on GitHub.
github.com
# 3차 배포 내용
1. 카카오네비 설치 페이지
카카오 네비를 설치 하지 않았을 경우, 카카오 설치 페이지로 이동하게 만들었다. 처음부터 이렇게 만들었어야 하는데
세세한 부분을 고려하지 못하고, 카카오 네비가 설치되었다는 가정하에 만든 것이 내 실수였다.
또한 카카오 네비 말고, T맵 API나 네이버 지도 API를 추가로 만들려고 했지만, 이상하게 T맵 api가 작동하지 않았다.
T맵 홈페이지에서는 api 요청이 잘 들어온다고 뜸에도 불구하고, 버튼을 눌러도 아무런 반응이 나오지 않았다.
(로그를 찍었으나 에러조차도 뜨지 않음...)
다른 네비를 추가로 도입하는 것은 다음 업데이트때 고려하기로 하고, 일단 어쩔 수 없이 카카오 네비 api만 사용하는 것으로 마무리 지었다.
근데 왜 안된거지?? 진짜??..
2. 거리 단위 m -> km 변경
거리를 m단위로 설정하니, 거리를 표시하는데 차지하는 공간도 크고, 보기에 있어서 불편한 점이 있었다.
km 단위로 바꾸어 사용자들에게 보여주는 것이 보기에도 편하고, 부피도 줄어들어 km로 변경하였다.
3. MVVM 아키텍처 패턴 적용
장기간 주유소 어플을 지속적으로 유지보수하면서 드는 생각은 기능을 도입할때마다 메인엑티비티에 무작정 코드를 써야한다는 점이였다. 코드 양도 방대해질 뿐만 아니라 유지보수를 할때 코드를 일일히 다시 이해하고, 레트로핏 라이브러리를 적용함에 있어서 MVC 패턴으로는 한계가 있다고 판단되어 아키텍처 자체를 바꿨다.
보통 회사 공고에 안드로이드 기술 스택을 보면 MVVM 패턴이 필수로 들어가있는데,
그 이유에 대해 어느 정도 이해가 가게 되었다.
확실히 패턴을 적용하니 메인 엑티비티의 코드의 양 자체가 줄어들었고, View - viewModel - Model 등 각자 수행하는 역할이 모듈화 됨으로 유지 보수하기가 훨씬 편리해졌다.
그렇다고 MVC패턴이 나쁘다는 것은 아니였지만, 단기간에 어플을 만드는 것이 아닌 장기간에 어플을 유지보수 할 생각이였기 때문에 많은 시간과 노력이 들더라도 MVVM패턴을 적용하는 것이 장기간으로 보면 매우 좋은 선택이였다.
글씨가 좀 개판있지만, 구조를 적용하면 이런식으로 만들었다. 이게 정확한 MVVM 패턴인지는 좀 더 공부가 필요하겠지만,
그래도 각 역할을 모듈화/분업화 하니 훨씬 유지보수가 편리해졌다.
4. 레트로핏 라이브러리 사용
사실 레트로핏을 적용한 이유는 주유소 상세정보에 편의점과 세차장 유무를 사용자에게 \
편리하게 보여주기 위해 적용하였다.
또한 HttpClient와 요즘 레트로핏 라이브러리는의 차이점을 알고, 레트로핏의 사용방법을 익히고자 적용하였다.
사실 MVVM 패턴을 적용한 것도 레트로핏 라이브러리 보다 더 편하게 적용하기 위해 구성 한 것이다.
업데이트 이전에는 api를 단 한번만 호출하여, 사용자가 원하는 조건에 맞는 전체 주유소 리스트를 호출하여 리사이클러뷰에 보여주는 방식이였다면,
주유소 상세 정보 즉 (이름,주소, 세차장과 편의점 유무, 전화 번호는)에 대한 정보는 한번 호출한 api 정보안에서
주유소의 uid를 매개변수로 추가적인 api를 호출하여 응답받은 주유소의 상세정보까지 합쳐 list에 저장하는 방식으로
바뀌었다..
이전 방식은 주유소의 전체 리스트를 한번만 호출하여 보여주는 방식이라 속도가 빨랐지만, 세차장과 편의점 유무 정보등 추가적인 상세정보도 사용자에게 보여주는 방식이라 정보를 보여주는데 좀 더 오랜 시간이 걸렸다.
속도적인 면에서는 이전이 더 나을수 있다는 생각이 들지만,
세차장과 편의점 유무는 사용자에게 보다 편리한 정보 인 것 같아 업데이트 하였다.
1 2 3 4 5 6 7 8 9 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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | public class GetOilRepository { private Retrofit retrofit; private final static String BASE_URL = "http:///www.opinet.co.kr/"; RetrofitAPI retrofitAPI; List<oil_list> moil_list; private String apiKey = BuildConfig.GAS_API_KEY; private MyRecyclerAdapter myRecyclerAdapter; String oil = ""; public GetOilRepository(Application application){ super(); moil_list = new ArrayList<>(); retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); retrofitAPI = retrofit.create(RetrofitAPI.class); } public void getOilDetail(String sort, int size, RecyclerView mRecyclerView, GoogleMap mMap,String uid,String name,String gas_price,String distance,String inputOil, int imageResource,float getX,float getY){ retrofitAPI.getOilDetail(apiKey,"json",uid) .enqueue(new Callback<OilDetail>() { @Override public void onResponse(Call<OilDetail> call, Response<OilDetail> response) { if(response.isSuccessful()){ OilDetail oilDetail = response.body(); org.techtown.find_gas_station.Retrofit.oilDetail.RESULT result = oilDetail.getRESULT(); //세차장, 편의점 정보 String carWash = result.getOIL()[0].getCAR_WASH_YN(); String conStore = result.getOIL()[0].getCVS_YN(); //상세 정보 받아오기 String lotNumberAddress = result.getOIL()[0].getVAN_ADR(); String roadAddress = result.getOIL()[0].getNEW_ADR(); String tel = result.getOIL()[0].getTEL(); String sector = result.getOIL()[0].getLPG_YN(); int dis = (int)Double.parseDouble(distance); //소수점 짜르기 moil_list.add(new oil_list(uid,name,gas_price, Integer.toString(dis), inputOil,imageResource,getX,getY,carWash,conStore,lotNumberAddress,roadAddress, tel,sector)); //한번 응답 받은 전체 리스트 주유소 정보와 주유소 상세정보를 포함에 리스트에 넣어준다. //모두 받은 경우, 리사이클러 어뎁터를 호출하여 채운다. if(moil_list.size() == size){ if(sort.equals("1")){ Collections.sort(moil_list,new OilPriceComparator()); }//가격순 else{ Collections.sort(moil_list,new OilDistanceComparator()); }//거리순 //불필요한 정렬이 생성 //데이터는 제대로 들어감. myRecyclerAdapter = new MyRecyclerAdapter(moil_list,mMap); myRecyclerAdapter.notifyDataSetChanged(); //notifyDataSetChanged() 예외처리 실험 mRecyclerView.setAdapter(myRecyclerAdapter); } } } @Override public void onFailure(Call<OilDetail> call, Throwable t) { } }); } public void getOilList( RecyclerView mRecyclerView, GoogleMap mMap, String xPos, String yPos, String radius, String sort, String oilKind) { oil = oilKind; retrofitAPI.getOilList(apiKey, "json", xPos, yPos, radius,oilKind,sort) .enqueue(new Callback<MyPojo>() { @Override public void onResponse(Call<MyPojo> call, Response<MyPojo> response) { moil_list = new ArrayList<>(); //clear가 아닌 객체를 새로 생성 if(response.isSuccessful()){ MyPojo myPojo = response.body(); RESULT result = myPojo.getRESULT(); for(int i=0; i<result.getOIL().length; i++){ String uid = result.getOIL()[i].getUNI_ID(); //주유소 ID String distance = result.getOIL()[i].getDISTANCE(); //주유소 거리 String name = result.getOIL()[i].getOS_NM(); //주유소 이름(상호명) String gas_price = result.getOIL()[i].getPRICE(); //주유소 가격 //Log.e("TAG",name +" "+gas_price); String inputOil; if(oil.equals("B027")){ inputOil = "휘발유"; } else if(oil.equals("D047")){ inputOil = "경유"; } else if(oil.equals("B034")){ inputOil = "고급휘발유"; } else if(oil.equals("C004")){ inputOil = "실내등유"; } else inputOil = "자동차부탄"; float xPos = Float.parseFloat(result.getOIL()[i].getGIS_X_COOR()); //x좌표 위치 float yPos = Float.parseFloat(result.getOIL()[i].getGIS_Y_COOR()); //y좌표 위치 GeoTransPoint point = new GeoTransPoint(xPos,yPos); GeoTransPoint out = GeoTrans.convert(GeoTrans.KATEC, GeoTrans.GEO,point); //KATEC -> Wgs84좌표계로 변경 String trademark = result.getOIL()[i].getPOLL_DIV_CD(); //트레이드 마크 int imageResource; //이미지 리소스 if(trademark.equals("SKE")){ imageResource = R.drawable.sk; } else if(trademark.equals("GSC")){ imageResource = R.drawable.gs; } else if(trademark.equals("HDO")){ imageResource = R.drawable.hdoil; } else if(trademark.equals("SOL")){ imageResource = R.drawable.so; } else if(trademark.equals("RTO")){ imageResource = R.drawable.rto; }//비슷 else if(trademark.equals("RTX")){ imageResource = R.drawable.rto; }//비슷 else if(trademark.equals("RTX")){ imageResource = R.drawable.rto; } else if(trademark.equals("NHO")){ imageResource = R.drawable.nho; } else if(trademark.equals("E1G")){ imageResource = R.drawable.e1; } else if(trademark.equals("SKG")){ imageResource = R.drawable.skgas; } else imageResource = R.drawable.oil_2; getOilDetail(sort,result.getOIL().length,mRecyclerView,mMap,uid,name,gas_price,distance,inputOil, imageResource,(float)out.getX(),(float)out.getY()); //이미 받은 응답 데이터로 주유소의 상세정보 api 호출 } } } @Override public void onFailure(Call<MyPojo> call, Throwable t) { } }); } } | cs |
레트로핏 라이브러리를 사용하면서 제일 어려웠던 점은 비동기로 구현하다보니 가격순,거리순으로 정렬되었던 주유소 정보가 상세정보까지 합쳐지면서 정렬이 흐트러져 리사이클러뷰에 보여지는 문제가 있었다.
이를 막기 위해 추가로 Collections.sort를 이용해 정렬을 하였지만, 이미 정렬되어 온 데이터를 다시 정렬하여 보여지니 시간이 더욱 길어지게 되었다. 비동기로 구현하는데 나타나는 어려움을 해결하는 것이 3차 업데이트를 하면서 처리해야 할 숙제이다.
'프로젝트 > Android Project) 가장 가까운 주유소 찾기 app' 카테고리의 다른 글
가장 가까운 주유소 찾기 (4차 업데이트) 내용 (2) (0) | 2023.09.21 |
---|---|
가장 가까운 주유소 찾기 (4차 업데이트) 내용 (1) (0) | 2023.09.21 |
가장 가까운 주유소 찾기 (2차 업데이트) 내용 (2) (0) | 2022.09.10 |
가장 가까운 주유소 찾기 (2차 업데이트) 내용 (1) (0) | 2022.09.09 |
가장 가까운 주유소 찾기 (2차 업데이트) 하기 전 리뷰 (0) | 2022.07.05 |