본문 바로가기
Android Studio(Java)

Android Studio Retrofit (1)

by 히예네 2023. 3. 16.
728x90
반응형

step1. 사전작업 : 라이브러리 3개 추가, 뷰바인딩

Retrofit2버전을 쓰려면 라이브러리에 3개를 추가해줘야한다. (세트라고 생각하면 된다. )

※ 구글 볼리도 많이 쓴다.

라이브러리명  회사명 기능
retrofit2 squareup 통신하기 위한 코드를 써주는 객체
gson google API를 통해 Json으로 값을 내려받으면 자동으로 파싱해주는 객체
converter-gson squareup Gson과 Retrofit을 연결을 도와준다.

Retrofit은 AI처럼 Http~ 네트워크 코드를 자동으로 써주게 된다. 그러나 json을 객체로 파싱하는 능력은 갖고있지 않다 →이걸 하는것은 Gson이다. 이게 있으면 json을 객체로 쉽게 만들수있다. gson은 json에 특화되어있고, 이것을 분석할 때는 gson도 같이 쓴다.

Retrofit은 json이라는 글자열을 분석하는데 최적화이다. 그래서 GSON을 자주 같이 쓴다.

structure에서 라이브러리를 추가한다.

※ 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 Retrofit (2)

step2-2. 경로의 이름을 고정하지 않고 사용자에게 파라미터로 전달받아서 지정하자. @Path @Path로 하는 방법. 경로를 중괄호로 열어준다. 정하지 않은 변수라는뜻. 이름을 아무렇게나 써도 된다. ※

kofathena.tistory.com

 

728x90
반응형

'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