Skip to content

Latest commit

Β 

History

History
386 lines (295 loc) Β· 13.9 KB

Recyclerview_sieun.md

File metadata and controls

386 lines (295 loc) Β· 13.9 KB

0.μ°Έκ³ λ¬Έμ„œ

https://developer.android.com/reference/android/support/v7/widget/RecyclerView

http://liveonthekeyboard.tistory.com/135

http://www.kmshack.kr/2014/10/android-recyclerview/

[λ£¨λΉ„νŽ˜μ΄νΌ] 될 λ•ŒκΉŒμ§€ μ•ˆλ“œλ‘œμ΄λ“œ (μ˜€μ€€μ„)

1.Recyclerview

1.1. μ†Œκ°œ

  • 기쑴의 ListViewλŠ” μ»€μŠ€ν…€ν•˜κΈ°μ—λŠ” ꡬ쑰적인 문제둜 λ§Žμ€ μ œμ•½μ΄ λ”°λžμœΌλ©°, ꡬ쑰적인 문제둜 인해 μ„±λŠ₯λ¬Έμ œκ°€ μžˆμ—ˆλ‹€. κ·Έλž˜μ„œ 이 λ¬Έμ œλ“€μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ’€ 더 λ‹€μ–‘ν•œ ν˜•νƒœλ‘œ κ°œλ°œμžκ°€ μ»€μŠ€ν…€ν•  수 μžˆλ„λ‘ λ§Œλ“€μ–΄μ§„ 것이 RecyclerView!

  • 기쑴의 ListView보닀 μœ μ—°ν•˜κ³  μ„±λŠ₯이 ν–₯μƒλœ κ³ κΈ‰ μœ„μ ―

  • 리슀트λ₯Ό ν‘œμ‹œν•˜κΈ° μœ„ν•œ μ–΄λŒ‘ν„°λ·°λ₯Ό μ’€ 더 κ°œμ„ ν•œ μ»΄ν¬λ„ŒνŠΈ

  • 큰 틀은 μœ μ§€ν•œ 채 λ°μ΄ν„°λ§Œ λ°”λ€œ

  1. μ–΄λŒ‘ν„°λ·°μ™€μ˜ 차이점
    1. RecyclerViewλŠ” λ ˆμ΄μ•„μ›ƒ λ§€λ‹ˆμ €(LayoutManager)λ₯Ό 지정해 μ€˜μ•Ό 함
    2. μ–΄λŒ‘ν„°λ·°μ—μ„œλŠ” μ„ νƒμ‚¬ν•­μ΄μ—ˆλ˜ 뷰홀더 패던이 RecyclerViewμ—μ„œλŠ” κΌ­ κ΅¬ν˜„ν•΄μ•Ό 함
    3. μ–΄λŒ‘ν„°λ·°λŠ” 미리 제곡된 μ–΄λŒ‘ν„°κ°€ μžˆλŠ” 반면 RecyclerView의 μ–΄λŒ‘ν„°λŠ” 아무것도 μ œκ³΅ν•΄ 주지 μ•ŠμŒ
  2. μž₯점
    1. ViewHolderνŒ¨ν„΄μ„ μ μš©ν•˜μ—¬ λ·°λ₯Ό μž¬ν™œμš©
    2. Swipeλ₯Ό μ΄μš©ν•˜μ—¬ 직관적인 Refresh UIꡬ쑰 섀계가λŠ₯
    3. position에 λ”°λΌμ„œ ν•œ 리슀트 λ‚΄μ—μ„œ λ‹€μ–‘ν•œ λ·°λ₯Ό ν‘œν˜„κ°€λŠ₯(MultiView)
  3. 단점
    1. 이벀트 λ¦¬μŠ€λ„ˆμ™€ μ»€μ„œ(Cursor)λ₯Ό μ§€μ›ν•˜μ§€ μ•ŠμŒ

1.2. μ£Όμš” 클래슀

  • RecyclerView.Adapter
    μ–΄λŒ‘ν„°λ·°μ˜ μ–΄λŒ‘ν„°μ™€ 같은 μ—­ν• 
  • RecyclerView.ViewHolder
    뷰홀더 ν΄λž˜μŠ€λŠ” 이것을 상속해야함
  • LayoutManager
    데이터λ₯Ό λ°°μΉ˜ν•˜κ³ , 뷰의 μž¬μ‚¬μš© 등을 κ²°μ •ν•˜λŠ” 역할을 ν•˜μ—¬ 기쑴의 μ–΄λŒ‘ν„°λ·°λ³΄λ‹€ μ„±λŠ₯이 κ°œμ„ λ¨
    • LinearLayoutManager : 데이터λ₯Ό 리슀트뷰처럼 μ„Έλ‘œλ‚˜ κ°€λ‘œ ν•œ μ€„λ‘œ ν‘œμ‹œ

    • GridLayoutManager : κ·Έλ¦¬λ“œλ·°μ²˜λŸΌ 데이터λ₯Ό κ·Έλ¦¬λ“œ ν˜•μ‹μœΌλ‘œ ν‘œμ‹œ

    • StaggeredGridLayoutManager : κ·Έλ¦¬λ“œλ·°μ²˜λŸΌ 데이터λ₯Ό 격자 ν˜•μ‹μœΌλ‘œ ν‘œμ‹œν•˜λ©΄μ„œ μ•„μ΄ν…œμ˜ 높이가 μΌμ •ν•˜μ§€ μ•Šμ•„λ„ λ˜λŠ” μ§€κ·Έμž¬κ·Έν˜• κ·Έλ¦¬λ“œ ν˜•μ‹μœΌλ‘œ ν‘œμ‹œ

  • RecyclerView.ItemAnimation
    μ•„μ΄ν…œμ΄ μΆ”κ°€, μ‚­μ œ λ˜λŠ” μž¬μ •λ ¬λ  λ•Œ μ• λ‹ˆλ©”μ΄μ…˜ μ •μ˜
  • RecyclerView.ItemDecoration
    μ•„μ΄ν…œμ„ μ„ΈλΆ€μ μœΌλ‘œ 꾸밈

1.3. 예제

1.3.1.RecyclerView + CardView μ‚¬μš©
  1. 라이브러리 쒅속성 μΆ”κ°€

    dependencies{
        ...
    	implementation 'com.android.support:recyclerview-v7:26.1.0'
    	implementation 'com.android.support:cardview-v7:26.1.0'   
    }
  2. CardView λ ˆμ΄μ•„μ›ƒ μž‘μ„±

  3. μ–΄λŒ‘ν„° μž‘μ„±

    • RecyclerView.Adapterλ₯Ό 상속받아 κ΅¬ν˜„ν•΄μ•Ό 함

    • λΆ€λΆ„μ—λŠ” RecyclerView.ViewHolder 클래슀λ₯Ό μƒμ†ν•œ 뷰홀더 지정해야 함

      => ListViewμ—μ„œλŠ” 뷰홀더 νŒ¨ν„΄ μ‚¬μš©μ΄ ꢌμž₯μ‚¬ν•­μ΄μ—ˆμœΌλ‚˜, RecyclerViewλŠ” 의무

    import android.support.v7.widget.RecyclerView;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    import java.util.List;
    
    public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder>{
        private final List<CardItem> mDataList;
        public MyRecyclerAdapter(List<CardItem> dataList){
            mDataList = dataList;
        }
        // λ·° 홀더λ₯Ό μƒμ„±ν•˜λŠ” λΆ€λΆ„. λ ˆμ΄μ•„μ›ƒμ„ λ§Œλ“œλŠ” λΆ€λΆ„
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_card, parent, false);
            return new ViewHolder(view);
        }
        // λ·° 홀더에 데이터λ₯Ό μ„€μ •ν•˜λŠ” λΆ€λΆ„
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            // CardItemλŠ” μ•„μ΄ν…œμ— ν‘œμ‹œν•  데이터λ₯Ό κ°€μ§€λŠ” λͺ¨λΈ 클래슀
            CardItem item = mDataList.get(position);
            holder.title.setText(item.getTitle());
            holder.contents.setText(item.getContents());
        }
        //μ•„μ΄ν…œμ˜ 수
        @Override
        public int getItemCount() {
            return mDataList.size();
        }
        //각각의 μ•„μ΄ν…œμ˜ 레퍼런슀λ₯Ό μ €μž₯ν•  λ·° 홀더 클래슀
        //λ°˜λ“œμ‹œ RecyclerView.ViewHolderλ₯Ό 상속해야 함
        public static class ViewHolder extends RecyclerView.ViewHolder{
            TextView title;
            TextView contents;
    
            public ViewHolder(View itemview){
                super(itemview);
                title = itemview.findViewById(R.id.title_text);
                contents = itemview.findViewById(R.id.contents_text);
            }
        }
    }
  4. λ ˆμ΄μ•„μ›ƒ λ§€λ‹ˆμ €μ™€ μ–΄λŒ‘ν„° μ„€μ • - LinearLayoutManager

    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.GridLayoutManager;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.support.v7.widget.StaggeredGridLayoutManager;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
            //λ ˆμ΄μ•„μ›ƒ λ§€λ‹ˆμ €λ‘œ LinearLayoutManagerλ₯Ό μ„€μ •
            RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
            recyclerView.setLayoutManager(layoutManager);
            //ν‘œμ‹œν•  μž„μ‹œ 데이터
            List<CardItem> dataList = new ArrayList<>();
            // dataList.add(new CardItem(title, contents));
            dataList.add(new CardItem("이것은 첫번째 μ•„μ΄ν…œ", "μ•ˆλ“œλ‘œμ΄λ“œ 보이라고 ν•©λ‹ˆλ‹€"));
            dataList.add(new CardItem("이것은 λ‘λ²ˆμ§Έ μ•„μ΄ν…œ", "두 쀄 μž…λ ₯\n두 쀄 μž…λ‹ˆλ‹€"));
            dataList.add(new CardItem("이것은 μ„Έλ²ˆμ§Έ μ•„μ΄ν…œ", "세쀄\nλ‘λ²ˆμ§Έ 쀄\nμ„Έλ²ˆμ§Έ 쀄"));
            dataList.add(new CardItem("이것은 λ„€λ²ˆμ§Έ μ•„μ΄ν…œ", "잘 λ˜λ„€μš”!"));
            //μ–΄λŒ‘ν„° μ„€μ •
            MyRecyclerAdapter adapter = new MyRecyclerAdapter(dataList);
            recyclerView.setAdapter(adapter);
        }
    }

    1530258033138

    • λ ˆμ΄μ•„μ›ƒ λ§€λ‹ˆμ € μ½”λ“œ 정리

      • LinearLayoutManager

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);
      • GridLayoutManager

        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
        gridLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(gridLayoutManager);
      • StaggeredGridLayoutManager

        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2,
                 StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(gridLayoutManager);
1.3.2.클릭 이벀트 처리
  1. RecyclerView μ•„μ΄ν…œμ˜ 클릭 λ¦¬μŠ€λ„ˆλ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠλŠ”λ‹€

    =>λͺ¨λ“  μ΄λ²€νŠΈμ— λŒ€ν•œ 처리λ₯Ό κ°œλ°œμžκ°€ 직접 κ΅¬ν˜„ν•΄μ•Όν•¨

public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder>{
    private final List<CardItem> mDataList;
    private MyRecyclerViewClickListener mListener;
    ... μƒλž΅ ...
    public void setOnClickListener(MyRecyclerViewClickListener listener){
        mListener = listener;
    }
    public interface MyRecyclerViewClickListener {
        // μ•„μ΄ν…œ 전체 λΆ€λΆ„μ˜ 클릭
        void onItemClicked(int position);
        // share λ²„νŠΌ 클릭
        void onShareButtonClicked(int position);
        // Learn More λ²„νŠΌ 클릭
        void onLearnMoreButtonClicked(int position);
    }
}
  1. onBindViewHolder() λ©”μ„œλ“œμ—μ„œ 클릭이 λ°œμƒν•˜λŠ” 곳을 MyRecyclerViewClickListener와 μ—°κ²°
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {
   ... μƒλž΅ ...
    // λ·° 홀더에 데이터λ₯Ό μ„€μ •ν•˜λŠ” λΆ€λΆ„
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        CardItem item = mDataList.get(position);
        holder.title.setText(item.getTitle());
        holder.contents.setText(item.getContents());
        // 클릭 이벀트
        if (mListener != null) {
            // ν˜„μž¬ μœ„μΉ˜
            final int pos = position;
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mListener.onItemClicked(pos);
                }
            });
            holder.share.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View v) {
                    mListener.onShareButtonClicked(pos);
                }
            });
            holder.more.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mListener.onLearnMoreButtonClicked(pos);
                }
            });
        }
    }
    ... μƒλž΅ ...
    // 각각의 μ•„μ΄ν…œμ˜ 레퍼런슀λ₯Ό μ €μž₯ν•  λ·° 홀더 클래슀
    // λ°˜λ“œμ‹œ RecyclerView.ViewHolderλ₯Ό 상속해야 함
    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView title;
        TextView contents;
        Button share;
        Button more;

        public ViewHolder(View itemview) {
            super(itemview);
            title = itemview.findViewById(R.id.title_text);
            contents = itemview.findViewById(R.id.contents_text);
            share = (Button) itemview.findViewById(R.id.share_button);
            more = (Button) itemview.findViewById(R.id.more_button);
        }
    }
	... μƒλž΅ ...
}
  1. μ•‘ν‹°λΉ„ν‹°μ—μ„œ λ¦¬μŠ€λ„ˆ κ΅¬ν˜„, λ©”μ„œλ“œ μž¬μ •μ˜
public class MainActivity extends AppCompatActivity implements MyRecyclerAdapter.MyRecyclerViewClickListener{
    private static final String TAG = MainActivity.class.getSimpleName();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ... μƒλž΅ ...
        // μ–΄λŒ‘ν„° μ„€μ •
        MyRecyclerAdapter adapter = new MyRecyclerAdapter(dataList);
        adapter.setOnClickListener(this);
        recyclerView.setAdapter(adapter);
    }
    @Override
    public void onItemClicked(int position) {
        Log.d(TAG, "onItemClicked: " + position);
    }
    @Override
    public void onShareButtonClicked(int position) {
        Log.d(TAG, "onShareButtonClicked: " + position);
    }
    @Override
    public void onLearnMoreButtonClicked(int position) {
        Log.d(TAG, "onLearnMoreButtonClicked: " + position);
    }
}
  1. 콜백이 잘 λ™μž‘ν•˜λŠ”μ§€ 확인
1.3.3. μ• λ‹ˆλ©”μ΄μ…˜
  1. μ–΄λŒ‘ν„°λ·°μ—μ„œλŠ” 데이터가 λ³€κ²½λ˜μ—ˆμ„ λ•Œ 이λ₯Ό λ°˜μ˜ν•˜κΈ° μœ„ν•΄ notifyDataSetChanged() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ 데이터 변경을 ν†΅μ§€ν•˜κ³  λ·°κ°€ μƒμ‹ λ˜λ„λ‘ 함 => 항상 전체 ν•­λͺ©μ„ μƒˆλ‘œ λ‘œλ“œ

  2. RecyclerView의 μ–΄λŒ‘ν„°λŠ” 각 상황에 맞게 μ‚¬μš©ν•  수 μžˆλŠ” 톡지 λ©”μ„œλ“œ 제곡

    • notifyItemInserted(int position) : position μœ„μΉ˜μ˜ μ•„μ΄ν…œμ΄ μ‚½μž…λœ 것을 톡지
    • notifyItemRemoved(int position) : position μœ„μΉ˜μ˜ μ•„μ΄ν…œμ΄ μ‚­μ œλœ 것을 톡지
    public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {
        ... μƒλž΅ ...
        public void removeItem(int position){
            mDataList.remove(position);
            notifyItemRemoved(position);
            notifyItemRangeChanged(position, mDataList.size());
        }
        public void addItem(int position, CardView item){
            mDataList.add(position, item);
            notifyItemInserted(position);
            notifyItemRangeChanged(position, mDataList.size());
        }
    }
    • μœ„ λ©”μ„œλ“œλ“€μ€ μ•„μ΄ν…œμ΄ μΆ”κ°€, μ‚­μ œλ˜λ©΄μ„œ 기본적으둜 μ• λ‹ˆλ©”μ΄μ…˜μ΄ 지원됨
    • notifyItemRangeChanged(position, mDataList.size()) λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•΄μ•Ό μ œλŒ€λ‘œ μž‘λ™
      • 이 λ©”μ„œλ“œλŠ” 첫 번째 μΈμžλΆ€ν„° 두 번째 인자 μ‚¬μ΄μ˜ 데이터가 λ³€κ²½λ˜μ—ˆμŒμ„ 톡지
      • 이에 맞게 μ œλŒ€λ‘œ λ™μž‘ν•˜λ„λ‘ 함
  3. ItemAnimator와 ItemDecoration

    1. RecyclerViewλŠ” μ• λ‹ˆλ©”μ΄μ…˜ λͺ¨μ–‘을 κΎΈλ°€ 수 μžˆλŠ” 방법을 제곡

      • ItemAnimator

        • μ•„μ΄ν…œμ΄ μΆ”κ°€, μ‚­μ œ, 정렬될 λ•Œμ˜ μ• λ‹ˆλ©”μ΄μ…˜μ„ μ •μ˜ν•  수 μžˆλŠ” 클래슀
        • 이 클래슀λ₯Ό μƒμ†ν•˜λ©΄ μ—¬λŸ¬ 가지 좔상 λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•˜μ—¬ μ• λ‹ˆλ©”μ΄μ…˜ ꡬ성 κ°€λŠ₯
      • ItemDecoration

        • μ•„μ΄ν…œμ˜ λͺ¨μ–‘을 κΎΈλ°€ 수 μžˆλŠ” 클래슀

          DividerItemDecoration decoration = new DividerItemDecoration(this, layoutManager.getOrientation());
          recyclerView.addItemDecoration(decoration);
      • DefaultItemAnimator

        • RecyclerViewλŠ” νŠΉλ³„ν•œ 섀정이 μ—†μœΌλ©΄ λ―Έλ¦¬μ •μ˜λœ DefaultItemAnimatorκ°€ 적용됨

        • 이 ν΄λž˜μŠ€λŠ” μΆ”κ°€, μ‚­μ œ, μ •λ ¬ μ• λ‹ˆλ©”μ΄μ…˜μ˜ μ‹€ν–‰ 속도λ₯Ό μ‘°μ ˆν•  수 있음

          DefaultItemAnimator animator = new DefaultItemAnimator();
          animator.setAddDuration(1000);
          animator.setremoveDuration(1000);
          animator.setMoveDuration(1000);
          animator.setChangeDuration(1000);
          recyclerView.setItemAnimator(animator);