Today's

길을 나서지 않으면 그 길에서 만날 수 있는 사람을 만날 수 없다

모바일 앱(안드로이드)

안드로이드 앱 만들기 Recycle view 와 list view 의 차이가 뭘까 ?

Billcorea 2021. 8. 11. 12:41
반응형
 View rootView = LayoutInflater.from(context).inflate(R.layout.row_timeline, null, false);
        RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        rootView.setLayoutParams(lp);
        return new TimeLineViewHolder(rootView, viewType);

앱을 구현하다 보면 리스트를 목록 형태로 보여 주어야 하는 경우가 왕왕 발생 하게 된다.  이런 경우 주로 사용하는것이 예전에는 listview 을 많이 사용했는데, 이제는 recycleview 을 권장하는 시기가 되어 가는 것 같다.   나만의 생각일까 ?

뭐 암튼 recycleview 을 이용한 앱을 구현하는 동안 혼돈이 되었던 부분에 대한 기술을 해 두고자 한다.  먼저 recycleview 을 화면에 넣고 실행 했더니만...  layout 의 match_parent 가 적용 되지 않는다.  왜 ???

https://stackoverflow.com/questions/30691150/match-parent-width-does-not-work-in-recyclerview

 

match_parent width does not work in RecyclerView

My RecyclerView and item has match_parent width but the result is :

stackoverflow.com

잘 알 수는 없는 노릇이기는 하나,  아래 코드를 유의해서 보시길...

 View rootView = LayoutInflater.from(context).inflate(R.layout.row_timeline, null, false);
        RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        rootView.setLayoutParams(lp);
        return new TimeLineViewHolder(rootView, viewType);

recycleview 에 setLayoutParams 을 이용해서 파라미터를 전달하는 방식으로 witdh 을 match_parent 을 적용하였다.  그러면 끝.   

다음은, adapter 까지 잘 구현했나 싶은데...  화면에 아무것도 나오지 않는다.

https://recipes4dev.tistory.com/154

 

안드로이드 리사이클러뷰 기본 사용법. (Android RecyclerView)

1. 안드로이드 리사이클러뷰(RecyclerView) 리사이클러뷰(RecyclerView)는, "많은 수의 데이터 집합을, 제한된 영역 내에서 유연하게(flexible) 표시할 수 있도록 만들어주는 위젯"입니다. [안드로이드 개발

recipes4dev.tistory.com

 

listview 을 사용할 때는 고민하지 않았던 문제인데,  

        RecyclerView recyclerView = findViewById(R.id.recycler1) ;
        recyclerView.setLayoutManager(new LinearLayoutManager(this)) ;

layoutManager 는 왜 지정해야 하는 가? 하는 의문이 들기는 하지만, layoutManager 설정이 되어 있지 않으면,  화면에 표시가 되지 않는다.  java 에서 지정할 때는 위의 코드처럼 구현 하면 되고, layout 에서 지정할 수도 있으니 참고하시길.

listview 에서는 이름처럼 list 모양으로만 view 을 구현할 수 있지만, recycleview 의 경우는 layoutmanager 을 이용해서 다양한 모양의 view 을 구성해 줄 수 있기 때문에 layoutmanager 을 설정해 주어야 했다. 

 

https://developer.android.com/guide/topics/ui/layout/recyclerview-custom

 

RecyclerView 맞춤설정  |  Android 개발자  |  Android Developers

RecyclerView의 고급 맞춤설정 옵션

developer.android.com

 

또한 아래 예제에서 보여 주고 있는 것 처럼 adapter 을 구현하는 소스의 모양도 조금 다르니  구조를 보고 이해를 해 두는 것이 좋을 것 같다.  listview 을 활용하는 경우의 adapter 구현을 모양과 비교를 해 보면 거의 비슷해 보이기는 하나,  ViewHolder 을 기본으로 구현해 주고 있으니 잘 활용할 수 있으면 좋을 것 같다.  ViewHolder 을 구현하는 이유는 자원 재활용에 도움이 된다고 했던 것으로 본 기억이 있다.  list 가 스크롤 되면서 화면 밖으로 넘어가면 없어지고 그 자리를 다른 데이터로 채우는 모양으로 자원을 재활용 한다는 설명을 어딘가에서 보았던 기억이 난다.

public class SimpleTextAdapter extends RecyclerView.Adapter<SimpleTextAdapter.ViewHolder> {

    private ArrayList<String> mData = null ;

    // 아이템 뷰를 저장하는 뷰홀더 클래스.
    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView1 ;

        ViewHolder(View itemView) {
            super(itemView) ;

            // 뷰 객체에 대한 참조. (hold strong reference)
            textView1 = itemView.findViewById(R.id.text1) ;
        }
    }

    // 생성자에서 데이터 리스트 객체를 전달받음.
    public SimpleTextAdapter(ArrayList<String> list) {
        mData = list ;
    }

    // onCreateViewHolder() - 아이템 뷰를 위한 뷰홀더 객체 생성하여 리턴.
    @Override
    public SimpleTextAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Context context = parent.getContext() ;
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) ;

        View view = inflater.inflate(R.layout.recyclerview_item, parent, false) ;
        SimpleTextAdapter.ViewHolder vh = new SimpleTextAdapter.ViewHolder(view) ;

        return vh ;
    }

    // onBindViewHolder() - position에 해당하는 데이터를 뷰홀더의 아이템뷰에 표시.
    @Override
    public void onBindViewHolder(SimpleTextAdapter.ViewHolder holder, int position) {
        String text = mData.get(position) ;
        holder.textView1.setText(text) ;
    }

    // getItemCount() - 전체 데이터 갯수 리턴.
    @Override
    public int getItemCount() {
        return mData.size() ;
    }
}

 

이번에는 listview 을 지원하는 adapter 의 모양은 아래와 같다.

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import org.techtown.tab.databinding.ItemChattingListBinding;
import org.techtown.tab.model.ChatRooms;

import java.util.ArrayList;

public class ChatRoomAdapter extends BaseAdapter {

    ItemChattingListBinding binding ;
    ArrayList<ChatRooms> chattingListArrayList ;
    Context context ;
    LayoutInflater inflater;
    int nListCnt ;

    public ChatRoomAdapter(ArrayList<ChatRooms> oData, Context context) {
        this.chattingListArrayList = oData ;
        this.context = context ;
        this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        return chattingListArrayList.size();
    }

    @Override
    public ChatRooms getItem(int position) {
        return chattingListArrayList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public void updateReceiptsList(ArrayList<ChatRooms> _oData) {
        chattingListArrayList = _oData;
        nListCnt = chattingListArrayList.size(); // 배열 사이즈 다시 확인
        this.notifyDataSetChanged(); // 그냥 여기서 하자
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        binding = ItemChattingListBinding.inflate(inflater);
        CustomViewHolder holder ;
        if (convertView == null) {
            convertView = binding.getRoot();
            holder = new CustomViewHolder();
            holder.board = binding.boardingLocation2 ;
            holder.dest = binding.destination2;
            holder.chatMember = binding.boardingPeopleNum2;
            convertView.setTag(holder);
        } else {
            holder = (CustomViewHolder) convertView.getTag();
        }
        String strDest = chattingListArrayList.get(position).getDestination2() ;
        holder.board.setText(chattingListArrayList.get(position).getBoardingLocation2());
        holder.dest.setText(strDest);
        holder.chatMember.setText("" + chattingListArrayList.get(position).getBoardingPeopleNum2());
        return convertView;
    }

    private class CustomViewHolder {
        TextView dest ;
        TextView board ;
        TextView chatMember ;
    }
}

listview 을 이용하는 경우에도 viewHolder 을 사용하여 데이터를 저장하는 것이 listview 을 상하 스크롤를 하더라도 데이터가 없어지는 현상을 방지할 수 있었다.

오늘도 즐~

반응형