티스토리 뷰

모두를 충격과 공포에 빠뜨렸던 Adapter 디자인 패턴을 공부했습니다.



Adapter는 데이터 꾸러미들을 아래 자료처럼 리스트뷰에 맞춰서 알아서 출력을 해주는 도구입니다.


반복문으로 쌓아올리는것도 방법이 있지만, 이것을 자동화해주는 것이 Adapter라서 굉장히 유용할 것이라 생각합니다.

(대량의 경우에는 속도면에서도 조금 차이가 납니다.)


자세하게 알고 싶으시면 T아카데미 안드로이드 초급 RecyclerView 강의를 봐주세요


위에 보시면 아래쪽에 4가지 준비물이 필요하죠?


1. ArrayList<Data>  데이터 꾸러미

2. ListView(XML)      화면이 필요하구요

3. ItemLayout        데이터를 넣어서 보여줄 양식이 필요하겠죠?

4. Adpater            가장 중요한 데이터를 알맞게 변환시켜주는 기능입니다.



이 방법은 조금 어려웠어요...


먼저 데이터구조를 하나 만들구요


public class ListData {

private String mainText;
private String subText;
private int imgAddress;

public ListData(String mainText, String subText, int imgAddress) {
this.mainText = mainText;
this.subText = subText;
this.imgAddress = imgAddress;
}

public String getMainText() {
return mainText;
}
public void setMainText(String mainText) {
this.mainText = mainText;
}
public String getSubText() {
return subText;
}
public void setSubText(String subText) {
this.subText = subText;
}
public int getImgAddress() {
return imgAddress;
}
public void setImgAddress(int imgAddress) {
this.imgAddress = imgAddress;
}
}




다음으로 XML에 LIstView와 Itemlayout을 만들었습니다.


       


//리스트뷰가 들어있는 코드구요

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<ListView
android:id="@+id/listview"
android:dividerHeight="3dp"
android:layout_weight="1"
android:divider="@color/mainColor"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<Button
android:id="@+id/button"
android:text="버튼1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

</LinearLayout>



//리스트뷰에 들어갈 Itemlayout이 들어있는 코드입니다.(릴레이티브라 조금 복잡하네요)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
android:padding="10dp"
android:orientation="vertical">

<ImageView
android:src="@drawable/dco_b_sample_profile"
android:id="@+id/img"
android:scaleType="centerInside"
android:layout_width="80dp"
android:layout_height="80dp" />

<TextView
android:text="sampleString"
android:textSize="20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/img"
android:layout_toEndOf="@+id/img"
android:layout_marginLeft="29dp"
android:layout_marginStart="29dp"
android:id="@+id/mainText" />

<TextView
android:id="@+id/subText"
android:text="100"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/mainText"
android:layout_alignBottom="@+id/mainText"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="12dp"
android:layout_marginEnd="12dp" />



</RelativeLayout>



이렇게 레이아웃이 준비되었으면 Adapter를 만듭니다.


public class MyListAdapter extends BaseAdapter {

Context context;
int layout;
ArrayList<ListData> items;

/**
* 어댑터를 쓸때 필요한 부분들을 가져오는 생성자를 만든다.
* @param context 리스트를 보여주는 액티비티의 Contenxt : itemlayout을 inflate를 할때 필요하다.
* @param layout 데이터들을 담아둘 itemlayout Address : R.layout.sample_item 이들어오는 곳이다.
* 리소스 디렉토리내의 주소를 가져오므로 int로 저장된다.
* @param items 데이터 꾸러미를 가져온다.
*/
public MyListAdapter(Context context, int layout, ArrayList<ListData> items) {
this.context = context;
this.layout = layout;
this.items = items;
}

/**
* 어댑터를 사용하는 중간에 데이터가 바뀌었을 때
* @param items
*/
public void setItems(ArrayList<ListData> items) {
this.items = items;
notifyDataSetChanged(); //어댑터의 정보가 바뀌면 리스트뷰가 리프레시 하는 메소드
}

/**
* 데이터의 숫자를 리턴
* @return
*/
@Override
public int getCount() {
if(items == null) return 0;
else return items.size();
}

/**
* 선택된 데이터를 리턴
* @param position 위치에 따른 데이터
* @return postion에 해당되는 data를 리턴
*/
@Override
public Object getItem(int position) {
return items.get(position);
}

/**
* 식별가능한 수치를 리턴
* @param position 위치
* @return 위치를 식별자로 사용한다.
*/
@Override
public long getItemId(int position) {
return position;
}

/**
* 보여줄 화면을 만드는 메소드다.
* @param position 식별자를 리턴
* @param view 보여줄 화면(초기 null값이며, BaseAdapter를 그냥 쓸경우엔 텍스트 형태로 리턴할 수 있다.)
* @param viewGroup 이건 그룹핑하는건데 신경쓰면 머리아프므로 패스하자
* @return layout에 맞춰서 데이터를 넣은 형태를 리턴
*/
@Override
public View getView(int position, View view, ViewGroup viewGroup) {
//view가 null인지 부터 검사한다.
if(view == null){
//view에 우리가 원하는 layout 화면을 넣어준다.
view = View.inflate(context, layout, null);
}

//position에 따라 다른 정보를 보여주므로 데이터 꾸러미에서 position에 따른 데이터를 가져온다.
ListData item = items.get(position);

//layout에 들어가있는 객체들을 가져온다.
TextView mainText = (TextView) view.findViewById(R.id.mainText);
TextView subText = (TextView) view.findViewById(R.id.subText);
ImageView img = (ImageView) view.findViewById(R.id.img);

//가져온 객체에 데이터를 입력한다.
mainText.setText(item.getMainText());
subText.setText(item.getSubText());
img.setImageResource(item.getImgAddress());

//view를 완성했으므로 view를 리턴해주자
return view;
}
}


어렵지않게 Adpater를 완성했습니다. (사실 넘나 어렵...)


Adapter까지 완성했다면 이제 이 Adapter를 ListView에 연동시켜주는 일만 남았습니다.


public class SampleActivity extends Activity {

ListView listView; //리스트뷰 레퍼런스 선언

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sample);

//인위적으로 데이터를 하나 구성한다.
ArrayList<ListData> items = new ArrayList<>();
for(int i=0; i<10;i++)
items.add(new ListData("메인텍스트 입니다. "+ i, i+ "명이 듣고있습니다.", R.drawable.dco_b_logo));

//XML의 리스트뷰와 연결
listView = (ListView) findViewById(R.id.listview);

//어댑터를 생성한다.
MyListAdapter adapter = new MyListAdapter(SampleActivity.this, R.layout.sample_item, items);

//리스트뷰 - 어댑터 연결!!
listView.setAdapter(adapter);

//끝
}
}


자 어렵고 긴 코드는 어댑터만 있었습니다. 

어댑터를 생성할때 우리가 만든 생성자대로 사용했구요

MyListAdapter(사용하는 액티비티 Context, 사용할 itemlayout, 데이터꾸러미) 를  순서대로 넣어서

우리가 원하는 화면을 만들었습니다. 




이방법을 커스터마이징 하면 원하는 대로 리스트를 만들 수 있겠죠?