티스토리 뷰

Volley

원래 Volley로 만들어뒀던 통신을 Retrofit으로 갈아엎느라 진짜 일주일 내내 똥 쌌습니다.

사실 회처럼 날로 먹으려고 제대로 안 읽고 갖다붙이기만 하다가

, 멘탈 나가서

수많은 블로그 글들, Stack Overflow 반복해서 읽다보니 아주 얄팍한 깨달음이 왔고 금새 끝낼 수 있었습니다.

이걸 몰라서 그 많은 시간을 허공에 흩뿌렸나 싶더라구요... :sweat:

Volley를 사용한 기존 통신은

  1. BaseFrag에 기본 request 메소드를 작성해놓고
  2. view로 보여지는 fragment에서 이를 상속받아 사용하고,
  3. 해당 fragment에서successListener 로 adapter와 연결된 arr에 데이터를 추가하는 방식이었습니다.

처음 만들었을 땐 코드량을 획기적으로 줄였다면서 너무 행복했었습니다만...

Retrofit 공부를 위한 희생양이 되었습니다. 즐거웠다 ㅠ

SearchFrag


    private void requestPname(){ //입력값이 장소 이름일 때 출력
        Log.d("chk", "장소 리스트 이름 requestPname: start");
        final String pname = search;
        params.clear();
        params.put("pname", search);
        request("PlaceListName.do", successListener);
        //어댑터에 적용
        initRecyclerView();
    }
    private void requestPlocation(){ //입력값이 장소 지역일 때 출력
        Log.d("chk", "장소 리스트 지역 requestPlocation: start");
        final String plocation = search;
        params.clear();
        params.put("plocation", search);
        request("PlaceListLocation.do", successListener);
        //어댑터에 적용
        initRecyclerView();
    }
    private void requestPaddress(){//입력값이 장소 주소일 때 출력
        Log.d("chk", "주소 리스트 지역 requestPaddress: start");
        final String paddress = search;
        params.clear();
        params.put("paddress", search);
        request("PlaceListAddress.do", successListener);
        //어댑터에 적용
        initRecyclerView();
    }

    private void requestForData() { //입력값 없이 전체 출력
        //상속받은 부분
        Log.d("chk", "장소 리스트 전체 requestForData: start");
        params.clear();
        request("PlaceList.do", successListener);
        //어댑터에 적용
        initRecyclerView();
    }

    Response.Listener<String> successListener = new Response.Listener<String>() {
        //가져온 jsonArray arr에 추가
        @Override
        public void onResponse(String response) {
            try {
                JSONArray proArr = new JSONArray(response);
                Log.d("proArr", "onResponse:" + response);
                for (int i = 0; i < proArr.length(); i++) { //10보다 작은데 <10 해놓으니까 오류나지 멍청이 똥멍청이야!!!
                    JSONObject proObj = proArr.getJSONObject(i);
                    String pidx = proObj.getString("pidx");
                    String pname = proObj.getString("pname");
                    String pimage1 = proObj.getString("pimage1");
                    String pvisit = proObj.getString("pvisit");
                    String picon = proObj.getString("picon");
                    String pcategory = proObj.getString("pcategory");
                    String pphone = proObj.getString("pphone");
                    String pcontent = proObj.getString("pcontent");
                    //리스트에 보여줄 어레이에 추가
                    arr.add(i, new ItemData(pidx, pname, pimage1, pvisit, picon, pcategory, pphone, pcontent, "0"));

                    Log.d("chk1", "arr:" + arr.get(i).pName);
                }
                //데이터가 바꼈으니까 여기서 arr 변화를 notifychange해준다!
                adapter.notifyDataSetChanged();
                total=arr.size();
                tv_tit.setText(total+"개의 결과가 있습니다");
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    };

 

BaseFrag

public class BaseFrag extends Fragment {
    //Volley
    Map<String, String> params = new HashMap<String, String>();

    public BaseFrag() {
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }
    //Volley
    public void request(String url, Response.Listener<String> successListener){
        RequestQueue stringRequest = Volley.newRequestQueue(getActivity());
        url = Storage.HOME_URL+":8180/oop/" + url;

        StringRequest myReq = new StringRequest(Request.Method.POST, url,
                successListener, errorListener){
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                String str ="str";
                params.put("test",str);
                return params;
            }
        };
        myReq.setRetryPolicy(new DefaultRetryPolicy(3000, 0, 1f)
        );
        stringRequest.add(myReq);
    }
    Response.ErrorListener errorListener = new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d("ErrorResponse", "통신 실패");
        }
    };
}

 

Retrofit2

JSP로 만든 해당 서버의 서비스 파일을 doPOST로 설정해뒀기 때문에 get 메소드를 활용할 수 없었습니다.

아쉽지만 post라도 열심히 써봅니다.

ResponseGet

응답받을 JSON 데이터를 가지고

https://www.jsonschema2pojo.org/

에서 클래스를 만들어주면 다음과 같이 어노테이션을 예쁘게 달고 나옵니다.

public class ResponseGet {

    @SerializedName("pimage1")
    @Expose
    private String pimage1;
    @SerializedName("picon")
    @Expose
    private Object picon;
    @SerializedName("pcontent")
    @Expose
    private String pcontent;
    @SerializedName("pvisit")
    @Expose
    private String pvisit;
    @SerializedName("pphone")
    @Expose
    private String pphone;
    @SerializedName("plocation")
    @Expose
    private Integer plocation;
    @SerializedName("pname")
    @Expose
    private String pname;
    @SerializedName("pidx")
    @Expose
    private Integer pidx;
    @SerializedName("pcategory")
    @Expose
    private Integer pcategory;
    @SerializedName("paddress")
    @Expose
    private String paddress;

    public String getPimage1() {
        return pimage1;
    }

    public void setPimage1(String pimage1) {
        this.pimage1 = pimage1;
    }

    public Object getPicon() {
        return picon;
    }

    public void setPicon(Object picon) {
        this.picon = picon;
    }

    public String getPcontent() {
        return pcontent;
    }

    public void setPcontent(String pcontent) {
        this.pcontent = pcontent;
    }

    public String getPvisit() {
        return pvisit;
    }

    public void setPvisit(String pvisit) {
        this.pvisit = pvisit;
    }

    public String getPphone() {
        return pphone;
    }

    public void setPphone(String pphone) {
        this.pphone = pphone;
    }

    public Integer getPlocation() {
        return plocation;
    }

    public void setPlocation(Integer plocation) {
        this.plocation = plocation;
    }

    public String getPname() {
        return pname;
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public Integer getPidx() {
        return pidx;
    }

    public void setPidx(Integer pidx) {
        this.pidx = pidx;
    }

    public Integer getPcategory() {
        return pcategory;
    }

    public void setPcategory(Integer pcategory) {
        this.pcategory = pcategory;
    }

    public String getPaddress() {
        return paddress;
    }

    public void setPaddress(String paddress) {
        this.paddress = paddress;
    }
}

RetroBaseApiService

public interface RetroBaseApiService {
    @POST("PlaceList.do")
    Call<List<ResponseGet>> rPlaceList();

    @FormUrlEncoded
    @POST("PlaceListLocation.do")
    Call<List<ResponseGet>> rPlocation(@FieldMap HashMap<String, String> parameters);

    @POST("PlaceListName.do")
    Call<List<ResponseGet>> rPname(@FieldMap HashMap<String, String> parameters);

    @POST("PlaceListAddress.do")
    Call<List<ResponseGet>> rPaddress(@FieldMap HashMap<String, String> parameters);
}

통신에 필요한 apiService 인터페이스를 작성해줍니다. 저의 경우는 받아오는 JSON이 List 형태였기 때문에 ``Call<List>``으로 했습니다. JSON의 형태에 따라 다르게 작성해주시면 됩니다.

@POST("BASE_URL을 제외한 나머지 주소")

@FormUrlEncoded : 파라미터를 추가할 때 넣어줍니다.

@FieldMap : 요구되는 파라미터의 형태를 작성해주면 됩니다.

RetroClient

public class RetroClient {
    public static final String BASE_URL = Storage.HOME_URL + ":8180/oop/";
    private static RetroBaseApiService retroBaseApiService =null;

    public static RetroBaseApiService getRetroBaseApiService(){
        if(retroBaseApiService == null){
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            retroBaseApiService = retrofit.create(RetroBaseApiService.class);
        }
        Log.d("retrofit", "getRetroBaseApiService: returned");
        return retroBaseApiService;
    }
}

SearchFrag (view단)

...
public void requestRlocation(String type, String search, ArrayList<ItemData> arr){
        HashMap<String, String> params2 = new HashMap<>();
        params2.put(type, search);
        RetroClient.getRetroBaseApiService().rPlocation(params2).enqueue(new Callback<List<ResponseGet>>() {
            @Override
            public void onResponse(Call<List<ResponseGet>> call, retrofit2.Response<List<ResponseGet>>  response) {
                List<ResponseGet> result = response.body();
                Log.d("retrofit", "onResponse: success1" + result); //200 정상통신
                for(int i = 0; i<result.size(); i++){
                    String pidx = String.valueOf(result.get(i).getPidx());
                    String pname = result.get(i).getPname();
                    String pimage1 = result.get(i).getPimage1();
                    String pvisit = result.get(i).getPvisit();
                    String picon = (String) result.get(i).getPicon();
                    String pcategory = String.valueOf(result.get(i).getPcategory());
                    String pphone = result.get(i).getPphone();
                    String pcontent = result.get(i).getPcontent();
                    arr.add(i, new ItemData(pidx, pname, pimage1, pvisit, picon, pcategory, pphone, pcontent, "0"));
                    Log.d("retrofit", "arr:" + arr.get(i).getpName());
                }
                adapter.notifyDataSetChanged();
                total=arr.size();
                tv_tit.setText(total+"개의 결과가 있습니다");
            }
            @Override
            public void onFailure(Call<List<ResponseGet>>  call, Throwable t) {
                Log.d("retrofit", "onResponse: failed");
            }
        });
        initRecyclerView();
    }

전체적인 구조는 Volley에서와 유사합니다 (사실 그만 뜯어고치고 싶었어요. 그래서 dto로 사용한 arr 그대로 썼습니다)

통신 요청 보내고 받아온 Response는 adapter와 연결된 arr에 잘 넣어주고, 마지막으로 initRecyclerView(); 메소드로 RecyclerView와 연결해줍니다.

 

덧붙여서

  • 새로운 라이브러리라는 부담감 때문이었는지, 멀쩡하게 객체들 들어오고 있었는데, toString으로 확인이 안된다며 패닉상태에 빠졌습니다.
    • 하지만 그렇다고 해도 Stack Overflow에서 말하던 toString()이 아닌 string() 메서드로 원시데이터 확인하는 법은 아직도 모르겠습니다.
    • 왜 나한테만 없는거지 string() 메소드...?

    img
    열심히 통신하고 있던 레트로핏 맴도 몰라주고... 객체 숫자 세어보니 열심히 response가지고 오고 있었더라구요... 머씈...코씈...

img

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/07   »
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
글 보관함