일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 막내의막무가내 안드로이드
- Fragment
- 막내의막무가내 목표 및 회고
- 막내의막무가내 안드로이드 코틀린
- 막내의막무가내 플러터
- 막내의막무가내 코볼 COBOL
- 프로그래머스 알고리즘
- 막내의막무가내 코틀린 안드로이드
- flutter network call
- 주택가 잠실새내
- 막내의막무가내 일상
- 막내의막무가내 알고리즘
- 막무가내
- 2022년 6월 일상
- 부스트코스
- 막내의막무가내
- 안드로이드
- 주엽역 생활맥주
- 막내의막무가내 코틀린
- 막내의 막무가내 알고리즘
- 막내의막무가내 안드로이드 에러 해결
- 막내의막무가내 SQL
- 막내의막무가내 rxjava
- 부스트코스에이스
- 안드로이드 sunflower
- 막내의막무가내 플러터 flutter
- 안드로이드 Sunflower 스터디
- 프래그먼트
- 막내의 막무가내
- 막내의막무가내 프로그래밍
- Today
- Total
막내의 막무가내 프로그래밍 & 일상
[안드로이드] Retrofit2 정리 예제 본문
이번에는 레트로핏(Retrofit2)에 대해 정리해보는 포스팅을 가져보도록 하겠습니다.
http://www.kobis.or.kr/kobisopenapi/homepg/main/main.do
레트로핏 실습을 위해 영화진흥위원회 오픈 API를 참고하여 통신하도록 하겠습니다. 그 중에서도 주간/주말 박스오피스 순위기준으로(http://www.kobis.or.kr/kobisopenapi/homepg/apiservice/searchServiceInfo.do) 영화의 제목과 순위 일일관객수 누적관객수를 리사이클러뷰 형태로 불러와보도록 하겠습니다.
먼저 시작하기전에 해당사이트에서 회원가입을하고 api접근 허용키를 받아야 데이터를 불러올 수 있습니다.
1. 먼저 매니페스트에 인터넷접근권한을 추가해줍니다. 그리고 android:usesCleartextTraffic="true"도 application태그 안에 추가해주도록 합니다.
<uses-permission android:name="android.permission.INTERNET"/>
2. build.gradle에 추가해줍니다.
/*레트로핏2, GSON, 리사이클러뷰*/
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
3. 사이트에서 JSON 사이트에 접속합니다.
http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchWeeklyBoxOfficeList.json?key=430156241533f1d058c603178cc3ca0e&targetDt=20120101 |
4. 그럼 JSON형식으로 된 데이터들을 볼 수있을텐데 정렬되게 보기싶다면 https://youngest-programming.tistory.com/18
를 다운받아서 보시면 됩니다.!
5. 해당 JSON을 https://youngest-programming.tistory.com/72
를 참고해서 레트로핏통신을 해서 JSON -> GSON 변환이 가능하게 해줍니다. 이 사이트는 일일히 GSON으로 변환되게할 객체를 안만들어도되고 자동으로 JSON을 분석해서 자바클래스로 바꿔주는 역할을 합니다.
6. 이제 자바클래스를 만들었으면 먼저 xml 뷰를 어떻게 할지 보도록 하겠습니다. 매인액티비티xml과 리사이클러뷰 어댑터를 위한 아이템뷰 이렇게 2개를 만듭니다.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/boxoffice_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</LinearLayout>
boxoffice_item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="56dp"
android:gravity="center_vertical"
android:padding="8dp"
android:orientation="horizontal">
<TextView
android:id="@+id/rank"
android:layout_width="25dp"
android:background="#544B4B"
android:text="1"
android:textColor="#FFFFFF"
android:gravity="center"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/movie_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:text="어벤저스"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height= "match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/count1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/count2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
7. 이제 5번에서 변환한 것을 이용해 클래스를 생성해주도록합니다. 복사 붙여넣기 하시면됩니다.
JSON이 2중구조로 되있으니 데이터를 받는 클래스는 총 3개가 필요합니다.(변환사이트에 preview를 누르면 클래스가 3개가 나올겁니다. 그걸만드시면 됩니다. )
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/*
"boxOfficeResult": {
"boxofficeType": "주말 박스오피스",
"showRange": "20111230~20120101",
"yearWeekTime": "201152",
"weeklyBoxOfficeList": [
{
"rnum": "1",
"rank": "1",
"rankInten": "0",
"rankOldAndNew": "OLD",
"movieCd": "20112207",
"movieNm": "미션임파서블:고스트프로토콜",
"openDt": "2011-12-15",
"salesAmt": "7840509500",
"salesShare": "35.8",
"salesInten": "-1706758500",
"salesChange": "-17.9",
"salesAcc": "40541108500",
"audiCnt": "1007683",
"audiInten": "-234848",
"audiChange": "-18.9",
"audiAcc": "5328435",
"scrnCnt": "697",
"showCnt": "9677"
},
*/
import java.util.List;
public class BoxOfficeResult {
@SerializedName("boxofficeType")
@Expose
private String boxofficeType;
@SerializedName("showRange")
@Expose
private String showRange;
@SerializedName("yearWeekTime")
@Expose
private String yearWeekTime;
@SerializedName("weeklyBoxOfficeList")
@Expose
private List<WeeklyBoxOfficeList> weeklyBoxOfficeList = null;
public String getBoxofficeType() {
return boxofficeType;
}
public void setBoxofficeType(String boxofficeType) {
this.boxofficeType = boxofficeType;
}
public String getShowRange() {
return showRange;
}
public void setShowRange(String showRange) {
this.showRange = showRange;
}
public String getYearWeekTime() {
return yearWeekTime;
}
public void setYearWeekTime(String yearWeekTime) {
this.yearWeekTime = yearWeekTime;
}
public List<WeeklyBoxOfficeList> getWeeklyBoxOfficeList() {
return weeklyBoxOfficeList;
}
public void setWeeklyBoxOfficeList(List<WeeklyBoxOfficeList> weeklyBoxOfficeList) {
this.weeklyBoxOfficeList = weeklyBoxOfficeList;
}
}
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/*
* weeklyBoxOfficeList": [
{
"rnum": "1",
"rank": "1",
"rankInten": "0",
"rankOldAndNew": "OLD",
"movieCd": "20112207",
"movieNm": "미션임파서블:고스트프로토콜",
"openDt": "2011-12-15",
"salesAmt": "7840509500",
"salesShare": "35.8",
"salesInten": "-1706758500",
"salesChange": "-17.9",
"salesAcc": "40541108500",
"audiCnt": "1007683",
"audiInten": "-234848",
"audiChange": "-18.9",
"audiAcc": "5328435",
"scrnCnt": "697",
"showCnt": "9677"
},
{
"rnum": "2",
"rank": "2",
"rankInten": "1",
"rankOldAndNew": "OLD",
"movieCd": "20112621",
"movieNm": "셜록홈즈 : 그림자 게임",
"openDt": "2011-12-21",
"salesAmt": "3436042500",
"salesShare": "15.7",
"salesInten": "-576328500",
"salesChange": "-14.4",
"salesAcc": "10678327500",
"audiCnt": "453533",
"audiInten": "-83422",
"audiChange": "-15.5",
"audiAcc": "1442861",
"scrnCnt": "363",
"showCnt": "5589"
},
* */
public class WeeklyBoxOfficeList {
@SerializedName("rnum")
@Expose
private String rnum;
@SerializedName("rank")
@Expose
private String rank;
@SerializedName("rankInten")
@Expose
private String rankInten;
@SerializedName("rankOldAndNew")
@Expose
private String rankOldAndNew;
@SerializedName("movieCd")
@Expose
private String movieCd;
@SerializedName("movieNm")
@Expose
private String movieNm;
@SerializedName("openDt")
@Expose
private String openDt;
@SerializedName("salesAmt")
@Expose
private String salesAmt;
@SerializedName("salesShare")
@Expose
private String salesShare;
@SerializedName("salesInten")
@Expose
private String salesInten;
@SerializedName("salesChange")
@Expose
private String salesChange;
@SerializedName("salesAcc")
@Expose
private String salesAcc;
@SerializedName("audiCnt")
@Expose
private String audiCnt;
@SerializedName("audiInten")
@Expose
private String audiInten;
@SerializedName("audiChange")
@Expose
private String audiChange;
@SerializedName("audiAcc")
@Expose
private String audiAcc;
@SerializedName("scrnCnt")
@Expose
private String scrnCnt;
@SerializedName("showCnt")
@Expose
private String showCnt;
public String getRnum() {
return rnum;
}
public void setRnum(String rnum) {
this.rnum = rnum;
}
public String getRank() {
return rank;
}
public void setRank(String rank) {
this.rank = rank;
}
public String getRankInten() {
return rankInten;
}
public void setRankInten(String rankInten) {
this.rankInten = rankInten;
}
public String getRankOldAndNew() {
return rankOldAndNew;
}
public void setRankOldAndNew(String rankOldAndNew) {
this.rankOldAndNew = rankOldAndNew;
}
public String getMovieCd() {
return movieCd;
}
public void setMovieCd(String movieCd) {
this.movieCd = movieCd;
}
public String getMovieNm() {
return movieNm;
}
public void setMovieNm(String movieNm) {
this.movieNm = movieNm;
}
public String getOpenDt() {
return openDt;
}
public void setOpenDt(String openDt) {
this.openDt = openDt;
}
public String getSalesAmt() {
return salesAmt;
}
public void setSalesAmt(String salesAmt) {
this.salesAmt = salesAmt;
}
public String getSalesShare() {
return salesShare;
}
public void setSalesShare(String salesShare) {
this.salesShare = salesShare;
}
public String getSalesInten() {
return salesInten;
}
public void setSalesInten(String salesInten) {
this.salesInten = salesInten;
}
public String getSalesChange() {
return salesChange;
}
public void setSalesChange(String salesChange) {
this.salesChange = salesChange;
}
public String getSalesAcc() {
return salesAcc;
}
public void setSalesAcc(String salesAcc) {
this.salesAcc = salesAcc;
}
public String getAudiCnt() {
return audiCnt;
}
public void setAudiCnt(String audiCnt) {
this.audiCnt = audiCnt;
}
public String getAudiInten() {
return audiInten;
}
public void setAudiInten(String audiInten) {
this.audiInten = audiInten;
}
public String getAudiChange() {
return audiChange;
}
public void setAudiChange(String audiChange) {
this.audiChange = audiChange;
}
public String getAudiAcc() {
return audiAcc;
}
public void setAudiAcc(String audiAcc) {
this.audiAcc = audiAcc;
}
public String getScrnCnt() {
return scrnCnt;
}
public void setScrnCnt(String scrnCnt) {
this.scrnCnt = scrnCnt;
}
public String getShowCnt() {
return showCnt;
}
public void setShowCnt(String showCnt) {
this.showCnt = showCnt;
}
}
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Result {
@SerializedName("boxOfficeResult")
@Expose
private BoxOfficeResult boxOfficeResult;
public BoxOfficeResult getBoxOfficeResult() {
return boxOfficeResult;
}
public void setBoxOfficeResult(BoxOfficeResult boxOfficeResult) {
this.boxOfficeResult = boxOfficeResult;
}
}
8. 그리고 통신을 위한 인터페이스를 생성해주도록 합니다. 사이트에서 다음과같이 보면은 필수적으로 요청파라미터를 2개보내고(API키와 날짜) 어디로 요청을 해야하는지 url이 나와있습니다. 이것을 참고하시면 됩니다. 참고로 baseUrl은 쓰지 않도록합니다. (앞대가리 대표) 만약 요청파라미터가 필요없으면 그냥 () 비어써도 되지만 여기서는 필요합니다.
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface BoxOfficeService {
// http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.xml
@GET("/kobisopenapi/webservice/rest/boxoffice/searchWeeklyBoxOfficeList.json?")
Call<Result> getBoxOffice(@Query("key") String key,
@Query("targetDt") String targetDt);
}
9. 리사이클러뷰로 보여줘야하므로 어댑터를 미리 만들어보도록 하겠습니다. 영화제목과 순위 관객수를 뿌려줄겁니다.
(레트로핏 포스팅이므로 자세한 설명은 생략하도록 하겠습니다.)
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class BoxOfficeAdapter extends RecyclerView.Adapter<BoxOfficeAdapter.BoxOfficeViewHolder>{
List<WeeklyBoxOfficeList> weeklyBoxOfficeLists = new ArrayList<>();
Context context;
public BoxOfficeAdapter(List<WeeklyBoxOfficeList> weeklyBoxOfficeLists, Context context) {
this.weeklyBoxOfficeLists = weeklyBoxOfficeLists;
this.context = context;
}
@NonNull
@Override
public BoxOfficeViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View rootView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.boxoffice_item, viewGroup, false);
BoxOfficeViewHolder boxOfficeViewHolder = new BoxOfficeViewHolder(rootView);
return boxOfficeViewHolder;
}
@Override
public void onBindViewHolder(@NonNull BoxOfficeViewHolder boxOfficeViewHolder, int i) {
WeeklyBoxOfficeList weeklyBoxOfficeList = weeklyBoxOfficeLists.get(i);
boxOfficeViewHolder.rankTextView.setText(weeklyBoxOfficeList.getRank()+"");
boxOfficeViewHolder.movieNameTextView.setText(weeklyBoxOfficeList.getMovieNm());
boxOfficeViewHolder.count1TextView.setText(weeklyBoxOfficeList.getAudiCnt()); //일일 관객수
boxOfficeViewHolder.count2TextView.setText(weeklyBoxOfficeList.getAudiAcc()); //누적관객수
}
@Override
public int getItemCount() {
return weeklyBoxOfficeLists.size();
}
public class BoxOfficeViewHolder extends RecyclerView.ViewHolder {
TextView rankTextView;
TextView movieNameTextView;
TextView count1TextView;
TextView count2TextView;
public BoxOfficeViewHolder(@NonNull View itemView) {
super(itemView);
rankTextView = itemView.findViewById(R.id.rank);
movieNameTextView = itemView.findViewById(R.id.movie_name);
count1TextView = itemView.findViewById(R.id.count1);
count2TextView = itemView.findViewById(R.id.count2);
}
}
}
10. 마지막으로 메인액티비티에서 통신을 하고 데이터를 받아와서 리사이클러뷰에 뿌려줍니다. basUrl은 대표 url을 의미합니다. JSON이 2중 구조로 되있으므로 처음 데이터들을 받아오고 그 안의 WeeklyBoxOfficeList를 불러와서 해당 리스트의 데이터(클래스)를 어댑터에 add 해주도록합니다.
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
//http://www.kobis.or.kr/kobisopenapi/homepg/main/main.do
public class MainActivity extends AppCompatActivity {
final String BASE_URL = "http://www.kobis.or.kr";
Retrofit retrofit;
BoxOfficeService boxOfficeService;
RecyclerView boxoffice_recycler;
String API_KEY = "당신의키를입력하세요";
List<WeeklyBoxOfficeList> weeklyBoxOfficeLists = new ArrayList<>();
BoxOfficeAdapter boxOfficeAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
boxoffice_recycler= findViewById(R.id.boxoffice_recycler);
//Retrofit 객체생성
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
/*addConverterFactory(GsonConverterFactory.create())은
Json을 우리가 원하는 형태로 만들어주는 Gson라이브러리와 Retrofit2에 연결하는 코드입니다 */
boxOfficeService = retrofit.create(BoxOfficeService.class);
boxOfficeService.getBoxOffice(API_KEY, "20190608").enqueue(new Callback<Result>() {
@Override
public void onResponse(Call<Result> call, Response<Result> response) {
if (response.isSuccessful()){
Log.d("retro", 1+"");
Result result = response.body();
BoxOfficeResult boxOfficeResult = result.getBoxOfficeResult();
List<WeeklyBoxOfficeList> weeklyBoxOfficeListLIst2 = boxOfficeResult.getWeeklyBoxOfficeList();
for (WeeklyBoxOfficeList weeklyBoxOffice : weeklyBoxOfficeListLIst2){
weeklyBoxOfficeLists.add(weeklyBoxOffice);
}
boxOfficeAdapter = new BoxOfficeAdapter(weeklyBoxOfficeLists, MainActivity.this);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false);
boxoffice_recycler.setLayoutManager(linearLayoutManager);
boxoffice_recycler.setAdapter(boxOfficeAdapter);
}else{
Log.d("retro", 2+"Error");
}
}
@Override
public void onFailure(Call<Result> call, Throwable t) {
}
});
}
}
이제 실행을 하면 다음과같은 결과화면을 볼 수 있습니다.
딱히 보고싶은 영화는 없네요.. 어벤저스는이미봤구
이상 포스팅을 마치도록하겠습니다.
댓글과 공감은 큰힘이 됩니다. 감사합니다.
p.s) put방식
public interface MiniGramService {
@GET("/minigrams")
Call<List<MiniGram>> getMiniGram();
//서버에 데이터를 수정해달라고 요청하는 메서드
//"http://memolease.ipdisk.co.kr:1337/minigrams/id/{like:true}" 이런식으로 보내질거다.
//그냥 String으로 보내면 서버에 put을 할수없어서 UTF-8로 바꿔서 보내야하는데 이를 레트로핏에서 FORMURLENCODED로 해준다.
@FormUrlEncoded
@PUT("/minigrams/{id}")
Call<MiniGram> updateLike(@Path("id") String id, @Field("like") boolean like);
}
miniGramService.updateLike(heartEvent.getId(), heartEvent.isLike()).enqueue(new Callback<MiniGram>() {
@Override
public void onResponse(Call<MiniGram> call, Response<MiniGram> response) {
if(response.isSuccessful()){
Log.d("like update", "sucess");
}else{
Log.d("like update", "failed");
}
}
@Override
public void onFailure(Call<MiniGram> call, Throwable t) {
Log.d("like update", "not connected");
}
});
'안드로이드 > 자바 & Previous' 카테고리의 다른 글
[안드로이드] otto 라이브러리 ( An event bus by Square ) (0) | 2019.06.16 |
---|---|
[안드로이드] Spanny 라이브러리 (0) | 2019.06.15 |
파이어베이스 FCM 노티피케이션(notification)하는 방법 정리 2019 (41) | 2019.06.12 |
[안드로이드] 리사이클러뷰(RecyclerVeiw) xml 뷰 여러개 사용하는 법 (뷰홀더 2개 이상) (4) | 2019.05.28 |
[안드로이드] 애드몹 전면광고 달기 17버전 2019년도 (0) | 2019.05.19 |