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

리사이클러뷰 어댑터에서 api 연동하기

0 추천

안녕하세요, 개발 초보입니다.

버스 정류장의 노선도 위에 버스의 현재 위치를 시각화 하는 나타내는 기능을 구현하고 있습니다.

API와 리사이클러뷰를 이용하여 버스 노선도의 정류장들을 불러왔고 다른 API를 이용하여 각각 정류장마다 버스가 있는지 없는지를 검색하여 검색 결과가 존재할 때 해당 정보를 Textview에 나타내는 방법으로 설계하였습니다. 

버스 정류장의 개수가 버스마다 다른지라 정류장들을 불러온 리사이클러뷰의 어댑터에서 다른 API를 검색하려고 합니다. 링크 연동은 잘 되나 결과가 Textview에 나타나지 않습니다.

해결 방법을 아시는 분이 계신가요?

BusRouteMapMyAdapter.java

@Override
    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.tv2.setVisibility(View.VISIBLE);
        holder.tv3.setVisibility(View.VISIBLE);

        requestUrl = "http://ws.bus.go.kr/api/rest/buspos/getLowBusPosByRouteSt?serviceKey="+dataKey+"&busRouteId=100100110&startOrd="+ord+"&endOrd="+ord;
        try{
            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);
            InputStream is = url.openStream();
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

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

            int eventType = parser.getEventType();

            while(eventType != XmlPullParser.END_DOCUMENT){
                switch (eventType){
                    //case XmlPullParser.START_DOCUMENT:
                    //    list=new ArrayList<LowBusRouteItem>();
                    //    break;
                    //case XmlPullParser.END_DOCUMENT:
                    //    break;
                    //case XmlPullParser.END_TAG:
                    //    if(parser.getName().equals("itemList")&&item!=null){
                    //        list.add(item);
                    //    }
                    //    break;
                    case XmlPullParser.START_TAG:
                        //    if(parser.getName().equals("itemList")){
                        //        item = new LowBusRouteItem();
                        //    }
                        if(parser.getName().equals("busType"))
                            b_busType = true;
                        if(parser.getName().equals("congetion"))
                            b_congetion = true;
                        if(parser.getName().equals("lastStnId"))
                            b_lastStnId = true;
                        if(parser.getName().equals("plainNo"))
                            b_plainNo = true;
                        if(parser.getName().equals("stopFlag"))
                            b_stopFlag = true;
                        if(parser.getName().equals("vehId"))
                            b_vehId = true;
                        break;

                    case XmlPullParser.TEXT:
                        if(b_busType){
                            //item.setBusType(parser.getText());
                            //holder.tv2.setText(parser.getText());
                            b_busType=false;
                        }
                        else if(b_congetion){
                            //item.setCongetion(parser.getText());
                            holder.tv3.setText(parser.getText());
                            b_congetion=false;
                        }
                        else if(b_lastStnId){
                            //item.setLastStnId(parser.getText());
                            b_lastStnId=false;
                        }
                        else if(b_plainNo){
                            //item.setPlainNo(parser.getText());
                            b_plainNo=false;
                        }
                        else if(b_stopFlag){
                            //item.setStopFlag(parser.getText());
                            b_stopFlag=false;
                        }else if(b_vehId){
                            //item.setVehId(parser.getText());
                            b_vehId=false;
                        }
                        break;
                }
                eventType = parser.next();
            }
        }catch (Exception e){
            e.printStackTrace();
        }

 

 

 

 

익명입니다 (310 포인트) 님이 2021년 11월 8일 질문
먼저 위처럼 onBindViewHolder에서 API를 메인쓰레드에서 직접 호출하고 있는 건 좋은 생각이 아닙니다. 데이터를 화면에 제대로 보여주리라는 보장이 없고 되더라도 화면이 버벅거릴 가능성이 매우 큽니다.
어떤 데이터를 스크롤링할 때 관련데이터를 실시간으로 불러오는 건, 백엔드에서 데이터를 합쳐서 내려주면 좋은 데, 그렇지 않고 모바일에서 처리하려면 상황에 따라 복잡해 집니다.

제일 좋은 옵션은
1. 백엔드에서 필요한 데이터를 합쳐서 내려준다.
2. 1이 안되면, 리사이클러뷰가 페이징처리를 하지 않는다면,  두개의  API를 조인한다.  (RxJava나 Coroutine을 사용하면 어렵지 않게 처리할 수 있지만, 그냥 위처럼  직접 구현하실 경우는 좀 복잡해 집니다.)
3. 2번도 안될 경우는, 제일 복잡하게 처리하는 경우가 되는, 리사이클러뷰의 에 스크롤이벤트를  이용하거나 님처럼 onBindViewHolder 또는 attach, detatch event 등을 이용할 수도 있는데, 이 때 필요한 것이 API 호출이 일어나는 동안 스크롤이 발생할 경우 해당 API를 취소해 주어야 하고, 액티비티나 프레그먼트가 onStop 또는 onDestory 될 때  모든 API호출을 취소해 주어야 합니다. 그리고 이미 서버에서 가져온 데이터가 존재한다면 로컬에 보관해서 Cache를 처리해 줌으로써 성능향상을 시켜 줄 필요가 있습니다. 1, 2번의 방법을 사용하면 이런 부분들이 상대적으로 많이 간단해 집니다.
위의 옵션 중 제일 적합한 방법을 선택하세요.
댓글 감사합니다.
공공데이터포털에서 제공하는 오픈 API를 사용 중인데 제가 직접 백엔드에서 사용할 정보를 골라낼 수 있나요?
공공데이터포털 API에 대해서는 잘 모르겠지만, 님이 백엔드가 있다면 그렇게 할 수 있겠죠. 그렇지 않다면 1번 옵션은 불가능하구요. 3번은 구현을 하더라도 여러가지 에러 상황 등으로 인해 골치가 아프기 때문에, 되도록 3번은 선택하지 않으시길 바래요.

답변 달기

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