일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Kotlin
- dart
- RxAndroid
- 안드로이드 구글맵
- mfc
- android architecture component
- C/C++
- flutter firestore
- android push
- C++
- Rxjava2
- Python
- livedata
- 안드로이드
- Android
- 프로그래머스
- C
- kodility
- 알고리즘
- 코틀린
- FLUTTER
- Django REST
- NDK
- Java
- Django REST Android
- UWP
- Django REST framework
- RxJava
- Flutter TextField
- Android P
- Today
- Total
개발하는 두더지
[Android/안드로이드] 다음 쇼핑 api 를 이용한 상품 검색 프로그램 ( 다음 API, JSON, ListView 활용 ) 본문
[Android/안드로이드] 다음 쇼핑 api 를 이용한 상품 검색 프로그램 ( 다음 API, JSON, ListView 활용 )
덜지 2016. 7. 22. 03:05개요
다음에서 제공하는 쇼핑 api를 이용하여 URL에서 결과를 JSON으로 받아와서 JSON파서를 이용해
ArrayList에 저장하여 화면에 뷰를 출력
모바일 DB SQLite3에 저장하는 기능 추가 구현
결과물
1. 다음 API 사용 방법 및 활용
2. JSON , 파싱 이해 및 활용
3. CUSTOM LISTVIEW 이해 및 활용
4. 프로젝트 코드
네이버 블로그에서 가져오면서 사진이 전부..... 사라져버렸다.
다음 API 키를 발급받는다.
https://apis.daum.net/shopping/search?apikey=본인의KEY&q=상품명&result=20&pageno=1&output=json&sort=pop
다음과 같이 발급받은 KEY를 이용하여 쿼리를 만들 수 있다.
Root -> array -> channel -> item
Root와 channel 를 JSONObject 로 얻어온 뒤 item Array객체를 얻어와서 데이터를 파싱하면된다.
자세한건 다음 목차에서 살펴보겠다.
2. JSON , 파싱 이해 및 활용
org.json은 안드로이드 스튜디오에서는 내장되어 있다.
JSONObjectA modifiable set of name/value mappings. Names are unique, non-null strings. Values may be any mix ofJSONObjects
,JSONArrays
, Strings, Booleans, Integers, Longs, Doubles orNULL
. Values may not benull
,NaNs
,infinities
, or of any type not listed here.
// 주의할 점은 JAVA의 null은 데이터를 지우는데 쓰는것이고, JSONObject.NULL은 null 값을 넣는다는 것이다.
( 전자도 결국 null 값을 넣는게 아닌가? )
Warning: this class represents null in two incompatible ways: the standard Javanull
reference, and the sentinel valueNULL
. In particular, callingput(name, null)
removes the named entry from the object butput(name, JSONObject.NULL)
stores an entry whose value isJSONObject.NULL
.
public JSONObject (String json)Added in API level 1Creates a new
JSONObject
with name/value mappings from the JSON string.Parameters
json a JSON-encoded string containing an object. Throws
JSONException if the parse fails or doesn't yield a JSONObject
.public JSONObject getJSONObject (String name)
Added in API level 1Returns the value mapped by
name
if it exists and is aJSONObject
, or throws otherwise.Throws
JSONException if the mapping doesn't exist or is not a JSONObject
.
public JSONArray getJSONArray (String name)
Added in API level 1Returns the value mapped by
name
if it exists and is aJSONArray
, or throws otherwise.Throws
JSONException if the mapping doesn't exist or is not a JSONArray
.
JSONArrayA dense indexed sequence of values. Values may be any mix of
JSONObjects
, otherJSONArrays
, Strings, Booleans, Integers, Longs, Doubles,null
orNULL
. Values may not beNaNs
,infinities
, or of any type not listed here.
JSONArray
has the same type coercion behavior and optional/mandatory accessors asJSONObject
. See that class' documentation for details.
Root -> array -> channel -> item
item의 객체를 얻어오려면 다음 코드와 같다
// result는 쿼리 결과이고, 그 값(String) 으로 JSON 객체를 만든다.
// 트리구조라 생각해보면 Root를 시작으로 한 트리의 객체를 가지게 된다고 이해하면 된다.
JSONObject root = new JSONObject(result);// 우리가 원하는 item 은 Root 아래의 channel 트리에 있다.
// 루트에서 channel 이라는 이름을 가진 객체를 가지고와서 channel을 시작으로 하는 JSON 객체를 만든다.
JSONObject channelObject = root.getJSONObject("channel");// channel 에서 item 은 리스트로 구성이 되어있으므로 JSONArray 객체로 받아온다.
JSONArray itemArray = channelObject.getJSONArray("item");// ltem 의 갯수만큼 돌면서 ltem 안에 있는 Object를 가져와서 그 안에 있는 데이터를 하나씩 파싱한다.StringBuilder sb2 = new StringBuilder();for (int i=0; i< itemArray.length(); i++){
sb2.setLength(0);
JSONObject jsonItem = itemArray.getJSONObject(i);
String title = "Title : " + jsonItem.getString("title");
sb2.append(title + "\n");
String maker = "Maker : " + jsonItem.getString("maker");
sb2.append(maker + "\n");
String price = "Price : " + jsonItem.getInt("price_min") + " ~ " + jsonItem.getInt("price_max");
sb2.append(price + "\n");
Drawable image = loadImage(jsonItem.getString("image_url"));
listViewAdapter.addItem(false, image, sb2.toString());
}
상품명, 브랜드, 최저가격, 최대가격, 상품이미지를 가져와서 저장한 뒤 그 값을 ListAdapter에 add해주면 결과가 출력된다.
3. Custom ListView 구현 및 활용
private class ListViewAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<ListData> mItem = new ArrayList<ListData>();
public ListViewAdapter(Context context) {
super();
mContext = context;
}
public void allRemove(){
mItem.clear();
}
@Override
public int getCount() {
return mItem.size();
}
@Override
public Object getItem(int position) {
return mItem.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public void addItem(boolean check, Drawable image, String text) {
ListData addInfo = null;
addInfo = new ListData();
addInfo.mCheck = check;
addInfo.mImageView = image;
addInfo.mTextView = text;
mItem.add(addInfo);
}
public void remove(int position) {
mItem.remove(position);
dataChange();
}
public void dataChange() {
listViewAdapter.notifyDataSetChanged();
}
@Override
//position 행의 index
//convertView 행의 전체를 나타내는 뷰
// parent 부모 뷰 즉 리스트뷰
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
// 시스템으로부터 레이아웃 리소스를 인플레이트하는 객체를 얻어오기
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// 어댑터 객체 만들 떼 보여줄 행의 레이아웃을 정하듯이 inflate로 내가 만든 xml을 행의 레이아웃으로 지정
convertView = inflater.inflate(R.layout.listview_item, null);
// 뷰홀더는 내가 만든 행의 레이아웃의 속성들로 구성
viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox);
viewHolder.imageView = (ImageView) convertView.findViewById(R.id.imageView);
viewHolder.textView = (TextView) convertView.findViewById(R.id.textView);
// 커스텀 리스트 아이템의 UI 객체들을 미리 찾아서 Tag에 넣어두고 미리 찾아둔 tag를 꺼내 쓰는 방식
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// 뷰홀더 안의 실제 값
ListData mData = mItem.get(position);
viewHolder.checkBox.setChecked(mData.mCheck);
if (mData.mImageView != null) {
viewHolder.imageView.setVisibility(View.VISIBLE);
viewHolder.imageView.setImageDrawable(mData.mImageView);
} else {
viewHolder.imageView.setVisibility(View.GONE);
}
viewHolder.textView.setText(mData.mTextView);
return convertView;
}
}
BaseAdapter 를 상속받아 만든 리스트 어댑터로 리스트 뷰에서 내가 원하는 대로 리스트 행을 구현할 수 있다.</pre>
오버라이드된 getView 메소드는 리스트에 변화가 있을 때 마다 리스트 갯수 또는 그 이상 호출된다.
리소스와 속도 향상을 위해 ViewHolder라는 것을 사용한다.
/**
* Created by KJH on 2015-11-10.
* 전체가 public 으로 구현된 간단한 클래스로
* 멤버변수에 접근하는 비용을 줄이는 ViewHolder 패턴을 이용
* Row내의 요소 위젯들을 직접적으로 가지고 있으므로 바로바로 값을 변경할 수 있다.
* 실제로 많은 Row를 가져도 빠르게 동작한다.
*/
public class ViewHolder {
public CheckBox checkBox;
public ImageView imageView;
public TextView textView;
}
커스텀 어댑터를 리스트 뷰에 set 시켜주면 처음에 행을 나타내는 뷰는 구현이 되어있지 않다.
그래서 convertView 가 null 일 때, 리스트의 행 레이아웃을 구현해줘야 한다.
초반부에 말했듯이 getView는 리스트 갯 수 만큼 호출된다. 그런데 호출될 때 마다 새로운 레이아웃 객체를 만들어서
세팅해준다면 상당한 비용이 발생하게 된다.
그래서 뷰 홀더를 만들고 convertView 에 setTag(뷰 홀더); 로 저장해주고
getView가 호출될 때 마다 getTag()로 뷰 홀더를 가져오는 방식이다.
'Java,Android' 카테고리의 다른 글
[Android/안드로이드] Android 와 JSP 간 파라미터 암복호화 (2) (0) | 2016.07.22 |
---|---|
[Android/안드로이드] Android 와 JSP 간 파라미터 암복호화 (1) (0) | 2016.07.22 |
[Android/안드로이드] Service와 BroadcastReceiver로 스크린 화면 감지하기 (7) | 2016.07.22 |
[Android/안드로이드/자바] Thread, Runnable, Handler 에 대해 알아보기 (0) | 2016.07.22 |
[Android/안드로이드] 안드로이드 파일 탐색기 구현 (2) | 2016.07.22 |