마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

리사이클러뷰 어댑터에서 api 연동 질문 (코드 첨부)

0 추천

아래와 같이 리사이클러뷰 어댑터의 onBindViewHolder에서 공공데이터포털의 오픈 API를 연동하였습니다.

 

새로운 프로젝트를 만들어 똑같은 코드를 사용했을 때는 별 문제 없이 결과값이 나왔지만  onBindViewHolder에서 사용하니 try catch의 예외문으로 null값이 나옵니다.

 

이유가 뭔지 아시는 고수분 계신가요?

 

public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        holder.tv1.setText(mList.get(position).getStationNm());
        holder.tv_routId.setText(mList.get(position).getBusRouteId());
        holder.tv_seq.setText(mList.get(position).getSeq());
        busRouteId = mList.get(position).getBusRouteId();
        ord = mList.get(position).getSeq();
        holder.tv_routId.setText(busRouteId);
        holder.tv_seq.setText(ord);
        holder.tv3.setText(mList.get(position).getPlainNo());


        requestUrl =  "http://ws.bus.go.kr/api/rest/buspos/getLowBusPosByRouteSt?serviceKey="+dataKey+"&busRouteId=100100110&startOrd="+ord+"&endOrd="+ord;
        //"http://ws.bus.go.kr/api/rest/buspos/getBusPosByVehId?serviceKey=GiR2P0nFPyFyEt8y0fqQfpnAAr7tB9E%2BGV1rMbymFB4Y4CsNI5gON%2FVDs31BSgFwUUvqRVIvgXEKOUScetLEuQ%3D%3D&vehId=113062100";
        // http://ws.bus.go.kr/api/rest/buspos/getLowBusPosByRouteSt?serviceKey=GiR2P0nFPyFyEt8y0fqQfpnAAr7tB9E%2BGV1rMbymFB4Y4CsNI5gON%2FVDs31BSgFwUUvqRVIvgXEKOUScetLEuQ%3D%3D&busRouteId=100100110&startOrd=1&endOrd=75;

        try{
            boolean b_item = false;
            boolean b_plainNo = false;
            boolean b_vehId = false;
            boolean b_stopFlag = false;
            boolean b_busType = false;
            boolean b_lastStnId = false;
            boolean b_congetion = false;


            URL url = new URL(requestUrl); //검색 URL부분
            InputStream is = url.openStream();
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

            XmlPullParser parser = factory.newPullParser();
            parser.setInput(new InputStreamReader(is, "UTF-8"));

            int parserEvent = parser.getEventType();
            System.out.println("파싱시작합니다.");

            while (parserEvent != XmlPullParser.END_DOCUMENT){
                switch(parserEvent){
                    case XmlPullParser.START_TAG://parser가 시작 태그를 만나면 실행
                        if(parser.getName().equals("plainNo")){ //title 만나면 내용을 받을수 있게 하자
                            b_plainNo = true;
                        }
                        if(parser.getName().equals("vehId")){ 
                            b_vehId = true;
                        }
                        if(parser.getName().equals("stopFlag")){ 
                            b_stopFlag = true;
                        }
                        if(parser.getName().equals("busType")){ 
                            b_busType = true;
                        }
                        if(parser.getName().equals("lastStnId")){ 
                            b_lastStnId = true;
                        }
                        if(parser.getName().equals("congetion")){ 
                            b_congetion = true;
                        }
                        if(parser.getName().equals("message")){ //message 태그를 만나면 에러 출력
                            holder.tv2.setText(holder.tv2.getText()+"에러");
                            //여기에 에러코드에 따라 다른 메세지를 출력하도록 할 수 있다.
                        }
                        break;

                    case XmlPullParser.TEXT://parser가 내용에 접근했을때
                        if(b_plainNo){ 
                            plainNo = parser.getText();
                            b_plainNo = false;
                        }
                        if(b_vehId){                             vehId = parser.getText();
                            b_vehId = false;
                        }
                        if(b_stopFlag){ 
                            stopFlag = parser.getText();
                            b_stopFlag = false;
                        }
                        if(b_busType){ 
                            busType = parser.getText();
                            b_busType = false;
                        }
                        if(b_lastStnId){ 
                            lastStnId = parser.getText();
                            b_lastStnId = false;
                        }
                        if(b_congetion){ 
                            congetion = parser.getText();
                            b_congetion = false;
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        if(parser.getName().equals("itemList")){
                            //holder.tv2.setText(holder.tv2.getText()+"주소 : "+ plainNo +"\n 충전기 타입: "+ vehId +"\n 충전소ID : " + stopFlag
                            //       +"\n 충전기 명칭 : " + busType +  "\n 충전기 상태 코드 : " + lastStnId+ "\n 충전 방식 : " + congetion + "\n");
                            holder.tv2.setText("나이스~!~!: "+plainNo);
                            b_item = false;
                        }
                        break;
                }
                parserEvent = parser.next();
            }
        } catch(Exception e){
            holder.tv2.setText("에러가..났습니다..." + e.getMessage());
            System.out.println("tryError :" + e.getMessage());
        }
}

 

익명입니다 (310 포인트) 님이 2021년 11월 9일 질문
익명입니다님이 2021년 11월 9일 수정
안드로이드에서는 네트워크 호출은 메인쓰레드에서 할 수 없는게 기본 설정입니다. 왜냐하면 UI를 블록시키기 때문에 사용자에게 불편을 줄 가능성이 크기 때문입니다. 네트워킹 작업은 무조건 백그라운드에서 처리하셔야 해요.
현재처럼, 네트워크 관련 로직을 onBindViewHolder에서 하셔야 한다면 Glide의 소스를 체크해 보세요. 현재 님이 처리하시는 로직은 ViewHolder안에서 Glide를 통해 리모트에 있는 이미지를 가져와서 보여주는 것과 기능적으로는 같습니다.
https://github.com/bumptech/glide/tree/master/library
만약 Glide의 소스를 보시고 손댈 엄두가 나지 않는다면, 님이 처리하시려고 하는 작업이 기본적으로 그런 속성을 가지고 있다는 겁니다. 저같은 경우도 주식앱에서 리사이클러뷰 어댑터에서 실시간 가격변동을 보여주기 위해 1초마다 데이터를 끌고와서 보여주는 로직이 있는데(사용자가 스크롤을 하더라도 현재 보여지는 주식만 업데이트), 이게 님이 하려는 것과 비슷하긴한데, 저의 경우는 Kotlin과 ViewModel을 이용하고 있기 때문에 그나마 구현이 가능했던 것 같습니다.

답변 달기

· 글에 소스 코드 보기 좋게 넣는 법
· 질문에 대해 추가적인 질문이나 의견이 있으면 답변이 아니라 댓글로 달아주시기 바랍니다.
표시할 이름 (옵션):
개인정보: 당신의 이메일은 이 알림을 보내는데만 사용됩니다.
스팸 차단 검사:
스팸 검사를 다시 받지 않으려면 로그인하거나 혹은 가입 하세요.
...