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

ListView 상단으로 페이징 ?

0 추천
채팅 어플을 만드는 중에 마지막단에 막히는 부분이 있어 조언을 구하고자
글을 남깁니다.

채팅 내용 즉 주고 받은 대화가 어느정도 쌓여 있다는 가정, 그리고 채팅방을 나갔다가 재접근하는경우에
기존 채팅목록이 100개 이며, 마지막에 대화하나 내용을 20개 보여주고
상단으로 스크롤 할경우 비동기로 데이터를 불러와서, 이전 대화내용을 볼수 있는 upward paging 구현하고 있습니다.

기술적으로는  페이징할때 ListViewAdapter에서  List 데이터 객체를   LinkedList로 하여,   상단 객체 추가시addFirst 메서드를 사용해서 구현하고 있습니다.

문제는 여기서 아이템이 ListView추가될 때 좀더 부드럽게 스크롤링을 하고 싶은데,  말처럼 쉽지가 않네요.
상단으로 추가되는 아이템 만큼 ListView의 position과 높이를 구해서 기존 포지션을 유지하게 UI를 처리하려고 하며, 아래의 메서드로 처리해주고 있습니다.

public void addFirstItems(LinkedList<ChatMsg> msgList){

 

    this.lastTopPosition = mListView.getFirstVisiblePosition();
    int startCount = this.getCount();

    //scrolledToIndex = getListView().getFirstVisiblePosition();
    View v = mListView.getChildAt(0);
    topOffset = (v == null) ? 0 : v.getTop();

 

    for (int i = 0; i < msgList.size(); i++) {

        ChatMsg lastMsg = (i == 0) ? this.listData.getFirst() : msgList.get(i - 1);
        ChatMsg dateMsg = this.generateDateChatMsg(msgList.get(i), lastMsg,false);

        if(dateMsg != null){
            lastTopPosition++;
            this.listData.addFirst(dateMsg);
        }

        lastTopPosition++;
        this.listData.addFirst(msgList.get(i));

 

    } //end for____

 

    this.notifyDataSetChanged();

    
    this.handler.postDelayed(new Runnable() {
        @Override
        public void run() {
           //  mListView.setSelection(lastTopPosition);
            mListView.setSelectionFromTop(lastTopPosition,topOffset);

        }
    },0);
    

 

} //end method__

이것보다 더 나은 방법이 없는지 알고 싶습니다.
예를 들면 카카오톡 대화창에서 이전 대화내용을 보기위해서 위쪽으로 스크롤링하면,
상당히 부드럽게 처리되고 있습니다.
분명 묘책이 있을텐데, 카톡 어플을 디컴파일해서 보구 있는데, 난독화때문에 찾기 또한 힘드네요.

여러 고수님들의 조언 부탁드립니다.
파흔 (180 포인트) 님이 2015년 12월 30일 질문

2개의 답변

0 추천
android:stackFromBottom
익명사용자 님이 2015년 12월 30일 답변
0 추천
다른것보다 프로필 이미지등을 보여주는게 있는 경우에 속도에 크게 영향을 미치게 되는데

카톡의 경우 통신은 Volley 로 하고 이미지는 AUIL 로 하고 있을겁니다. (저도 카톡을 한번까본적이 있어서..)

텍스트 데이터와 이미지 데이터가 분리되어 있고 비동기식으로 호출하기 때문에

스크롤이 올라가서 데이터 요청시 텍스트 데이터만 요청해서 리스트뷰 아이템을 확장하고 그 뒤에

이미지를 비동기로 호출하는 하면서 cache 로 재활용하는 방법을 사용하기 때문에 속도가 빠르죠.

기본적인 데이터 호출과정에서 비용이 많이드는 부분은 없는지 부터 체크 하시고 구조 변경해야될껍니다.

또한 카톡같은 앱은 채팅방에서 호출하는 이미지도 원본이미지 사이즈가 아니라 최적화된 이미지 사이즈로

서버에서 저장하기 때문에 서버에서도 이런 부분이 고려되어야 합니다. 단순히 텍스트 데이터만 호출하는데

속도가 느려서 못해먹겠다면 코딩의 문제겠지요...ㅎ

위에 답변하신분 처럼 일단은 리스트구조를 역방향으로 출력하도록 작업하시는게 맞구요.

그뒤엔 제가 적어놓은 사항이 또 발목잡을 겁니다. 이론적으로만 적어놔서 도움이 될랑가 몰것네요.

그럼즐거운 고민하시길
라쎄린드 (25,460 포인트) 님이 2015년 12월 30일 답변
일단 답변 감사드립니다.
말씀하신데로  당연히 이미지 같은건 서버쪽에서 thumbnail 로 리사이징된 것을 비동기로 호출합니다. 속도의 문제가 아니라,  단지 스크롤링의 문제입니다.

 윗분의 말처럼  stackfrombottom 옵션으로는  해결이 되지 않는 문제입니다. !!

ListView row당 뷰가 아래서부터 쌓이는 문제가 아니라,  정확히 표현하자면 addItem 을 해서 일반적으로 객체가 추가될때의 row view는 객체가 많아져서, 화면에서 표시할수 없는 선을 넘어가면,  당연 아래로 지속적으로 쌓입니다.  
이와 마찬가지로  상단으로 객체가 추가될 때도 단말기 화면을 넘어서서 객체가 표시될때, 윗쪽으로 즉 화면밖으로  계속 view가 추되어져야한다는겁니다.   기존의 존재하는 row의 view가 아래로 밀려나면서 추가된느것이 아니라...

결국 LinkedList  Queue객체애서 addFirst를 통해서 새 데이터를 넣으면,   position = 0번에 객체를 추가하고,  기존이 있던 객체를 아래로 shift하는 개념이라,  상단에 추가되는 객체가 제일 상단에 무조건 보여지게됩니다.  

android:transcriptMode : disable상태에서  addItem했을때처럼, 추가되는 객체의 row의 view 가 리스트뷰의 상단으로 쌓여지데 ListView 화면 밖으로 쌓여져야한다는겁니다.

이게 가능한지가 포인트입니다.
...