step1. 사전작업 : 라이브러리 3개 추가, 뷰바인딩
Retrofit2버전을 쓰려면 라이브러리에 3개를 추가해줘야한다. (세트라고 생각하면 된다. )
※ 구글 볼리도 많이 쓴다.
라이브러리명 | 회사명 | 기능 |
retrofit2 | squareup | 통신하기 위한 코드를 써주는 객체 |
gson | API를 통해 Json으로 값을 내려받으면 자동으로 파싱해주는 객체 | |
converter-gson | squareup | Gson과 Retrofit을 연결을 도와준다. |
Retrofit은 AI처럼 Http~ 네트워크 코드를 자동으로 써주게 된다. 그러나 json을 객체로 파싱하는 능력은 갖고있지 않다 →이걸 하는것은 Gson이다. 이게 있으면 json을 객체로 쉽게 만들수있다. gson은 json에 특화되어있고, 이것을 분석할 때는 gson도 같이 쓴다.
Retrofit은 json이라는 글자열을 분석하는데 최적화이다. 그래서 GSON을 자주 같이 쓴다.
※ Gson과 Retrofit
Gson : json 문자열을 가져와서 Item객체에 하나하나 넣어주는 작업을 대신해주는객체. 아래 코드를 대신해준다.
- Gson 메소드
void clickBtn2(){
AssetManager assetManager = getAssets();
try {
InputStream is = assetManager.open("bbb.json");
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
StringBuffer buffer = new StringBuffer();
while (true){
String line = reader.readLine();
if(line==null) break;
buffer.append(line+"\n");
}
binding.tv.setText(buffer.toString());
JSONArray jsonArray = new JSONArray(buffer.toString());
for(int i=0; i<jsonArray.length(); i++){
JSONObject jo = jsonArray.getJSONObject(i);
int no = jo.getInt("no");
String name = jo.getString("name");
String msg = jo.getString("msg");
items.add(new Item(no,name,msg));
}
binding.tv.setText("아이템 개수 : "+items.size());
} catch (IOException e) {
throw new RuntimeException(e);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
Retrofit : 서버의 DB값을 load시켜준다. 네트워크 작업임. 아래 코드를 대신해준다
- void loadData()
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 이걸 대신한다.
void loadData(){ //29.
//테스트 데이터를 추가해보기
//items.add(new Item(1,"aa","aa","202344444"));
//items.add(new Item(2,"aaddd","aaddd","2023344444")); 테스트가 아주 잘됨!!
myadapter.notifyDataSetChanged(); //onCreate에서 아답터가 만들어졌으니까 리쥼에서 알려줘야함
//서버에 DB에 저장된 데이터들을 읽어오기
//30.네트워크 작업! 스레드가 필요하다
new Thread(){
@Override
public void run() {
//31. 서버 DB값을 에코시켜주는 php문서를 실행하자
String serverAddress="http://---------------/loadDB.php";
//이제 db값들을 에코시켜준다.
//32
try {
URL url = new URL(serverAddress);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoInput(true);
//connection.setDoOutput(true); 보낼게 없으니까 아웃풋은 필요없지
connection.setUseCaches(false);
InputStream is = connection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
StringBuffer buffer = new StringBuffer();
while (true){
String line = reader.readLine();
if(line==null) break;
buffer.append(line+"\n");
}
//33 잘 읽어왔는지 확인
runOnUiThread(()->{
new AlertDialog.Builder(BoardActivity.this).setMessage(buffer.toString()).create().show();
}); //토스트(최대 2줄)와 다르게 스크롤이됨
//34 loadDB. php파일 만들기 - 확인!
//35, 이제 저 파일을 안드로이드에서 읽어온다 서버에서 echo된 문자열데이터에서 우선 &를 기준으로 문자열을 분리하자
//한줄단위(Item)로 데이터를 분리...
String[] rows = buffer.toString().split("&");
Log.i("TAG",rows.length+""); //TAG찾기
//36. 한줄 데이터의 콤마구분자를 분리하여 값들 분석하기 [csv 파싱]
for(String row : rows){ // 문장이 여러개니까
String[] datas = row.split(","); //툭하니리턴받음
if(datas.length!=4) continue; //반복문의 현재번째만 안하는거
int no = Integer.parseInt(datas[0]);
String name = datas[1];
String msg = datas[2];
String date = datas[3]; //csv의 파싱은 특별한게 없다. 방에 값을 넣어주면 된다
//37. 대량의 데이터에 넣어준다.
items.add(new Item(no,name,msg,date));
}
//38. 리사이클러뷰의 화면갱신을 한다. 끝~
runOnUiThread(()->{
myadapter.notifyDataSetChanged();
});
//39. 이거랑 xml보다 더 쉽게 불러 올수 있지않을까? jason [{"식별자":"밸류","키":"밸류","키":"밸류"},{"키":"밸류","키":"밸류","키":"밸류"},{"키":숫자,"키":"밸류","키":"밸류"}]
//csv의 업그레이드버전 jason
//40. 로드DBphp를 jason 바꾼다 : loadDBtoJSON.php 파일 .. csv예제로 끝!
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}.start();
}
step2-1. get방식으로 서버에 있는 json 파일 읽어오기
버튼을 만들어서 예제별로 결과를 살펴보자
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:padding="8dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="32sp"
android:text="result"/>
<Button
android:id="@+id/btn1"
android:text="GET방식으로 JSON파일 가져오기"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
버튼을 눌렀을 때, get 방식으로 json문서를 읽어오자. clickBtn1()
public class MainActivity extends AppCompatActivity {
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding= ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot()); //Root는 LinearLayout이다.
binding.btn1.setOnClickListener(view->clickBtn1());
}
인터넷을 사용하기때문에 사전에 INTERNET permission을 받아둔다. (매니페스트)
우선 Visual Studio Code에 json파일을 만들자.
→ 파일명 : board.json
{"name":"sam","msg":"happy day"}
//{ "값" : "식별자" }
파일질라에 업로드하여 서버에 저장한다. (닷홈 사용자) html폴더 안에 넣어야한다.
만들어진 json 파일을 읽어와서 Item 객체로 곧바로 파싱까지 하자.
일단 Item class를 만들고 시작한다.
public class Item {
String name; //변수이름은 json파일에 있는 식별자와 똑같이 쓰기
String msg; //이게 틀리면 못받아온다.
public Item(String name, String msg) { //생성자는 없는것 있는것 두개 만들기
this.name = name;
this.msg = msg;
}
public Item() {
}
}
그리고 Retrofit작업을 실시한다. 총 5단계로 이뤄진다.
1 | 레트로핏 객체 생성 |
2 | 레트로핏 인터페이스(RetrofitService) 만들기 |
3 | 인터페이스 객체 생성 |
4 | 네트워크 작업하는 Call call 객체 생성 |
5 | call에게 네트워크 작업 지시 |
MainActivity.java
void clickBtn1(){
Retrofit.Builder builder = new Retrofit.Builder(); //1
builder.baseUrl("http:----------------------------");
builder.addConverterFactory(GsonConverterFactory.create()); //본인을 만드는 create()
//컨버터를 만드는 공장. 물건을 넘기지 말고 공장을 줘라! 필요할때마다 내가 만들께
//우리는 json을 읽을꺼니까 Gson이 적당해보인다.
//Retrofit한테 내가 Gson이 필요할때마다 꺼내서쓸께
Retrofit retrofit = builder.build();
//2. 인터페이스 만들기 **RetrofitService.java
//3. 설계한** RetrofitService 인터페이스 객체를 생성한다.
//추상메소드는 기능이 없다. new할 수 없다. 아무동작이 안된다.
//**대신 그 동작을 Retrofit이 대신해준다. 이때 내부코드를 써준다!!**
RetrofitService retrofitService = retrofit.create(RetrofitService.class);//3
//설계도면대로 할테니까 명세서(인터페이스.class)줘
Call<Item> call = retrofitService.getBoardJson();
//4. 위에서 만든 Service객체의 추상메소드를 호출하여
// 실제 네트워크 작업을 수행하는 Call 객체 생성
//getBoardJson()에는 이미 Retrofit Create해서 필요한 코드를 써줬다.
// 그 코드 써둔걸 Call이 받는것이다.
//5. 이제 call에게 네트워크 작업을 하게끔 하자
//스레드 만들필요가 없다. call이 다 해준다.
call.enqueue(new Callback<Item>() {//5
//결과를 기다리는 메소드
@Override
public void onResponse(Call<Item> call, Response<Item> response) {
//gson에 의해 자동으로 Item 객체로 파싱되어있는 데이터 값을 얻어오자
//json 글씨를 받는게 아니라 바로 Item을 받는다.
Item item = response.body();
binding.tv.setText(item.name+" : "+item.msg);
@Override
public void onFailure(Call<Item> call, Throwable t) {
binding.tv.setText("failure : "+ t.getMessage());
//Throwable t는 에러메세지를 던지는 녀석
}
💡 Call : 네트워크 작업을 해야할 때 필요한 코드를 갖고 있는 객체이다. (스레드 만들 필요 X)
💡 Retrofit은 통신을 위한 코드를 써주는 객체이다.
RetrofitService.java
이 안에는 Retrofit에게 의뢰하기 위한 요구 명세서를 쓰는것이다.
※내가 기능을 쓰는게 아니라, 요구사항(메소드 이름)만 쓰는것이다.
인터페이스는 추상메소드만 갖고있다. 이름만 있고 기능은 없다.
@어노테이션 : 강제주석 - 여기에는 방식을써준다. GET
( “ 폴더명 / 파일명 “ )
→ 이 파일을 접근하는데 GET방식으로 한다는 뜻이다. baseUrl뒤에 저절로 붙는다.
언제 저걸 하는데? 함수를 쓸때!
getBoardJson();
중괄호 없는 메소드를 만든다. 원래는 Stream만들고 ~~ 해줘야하는데 Retrofit이 자동으로 getBoardJson(); 를 실행하면 엄청 귀찮았던 코드(스트림, Url 등등)를 해줌.
이제!!!!!!!! 그 귀찮은 코드 글자를 실행해준다. 누가 ? Call
★ 그 글자를 써서 Call객체에 넣는다. 그리고 그걸 리턴해준다. Call 객체가 실제 네트워크작업을 호출한다. Call중에 retrofit꺼로 쓴다.
제네릭 : Retrofit에게 글씨써주고 Call에게 그 글씨를 넣는다. 그리고 Retrofit 이 통신하고 그 결과를 받아야하는데..? 나는 그 결과를 json으로 가져와서 Item으로 받고싶다.
제네릭에는 최종으로 받고 싶은 결과를 써준다. Item
Call<Item> getBoardJson();
public interface RetrofitService {
@GET("Retrofit/board.json")
Call<Item> getBoardJson();
}
이 방법의 단점은? 경로가 정해져있다. @GET("Retrofit/board.json")
→ 경로를 고정하지 않고 사용자에게 파라미터로 전달받아서 지정할 수 도 있다. 2-2
다음단계로
https://kofathena.tistory.com/42
'Android Studio(Java)' 카테고리의 다른 글
Android Studio Retrofit (3) (0) | 2023.03.19 |
---|---|
Android Studio Retrofit (2) (0) | 2023.03.16 |
Android Studio BackEnd (0) | 2023.03.10 |
Android Studio Fragment랑 FragmentActivity 차이점 (0) | 2023.03.06 |
Android Studio OpenAPI (0) | 2023.03.05 |