설.현.아빠
[ListView] Image+Text 성능 향상 버전 포함. 본문
<?xml version="1.0" encoding="utf-8"?>
<!-- main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- row.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TableLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TableRow>
<ImageView
android:id="@+id/imageview"
android:layout_width="120px"
android:layout_height="120px"
android:paddingLeft="10px"
android:paddingRight="10px"
/>
<TextView
android:id="@+id/label"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</TableRow>
</TableLayout>
</LinearLayout>
// Ex1020_002Activity.java
// Ex1020_001Activity.java는 002보다 성능이 향상된 버전이다.
package lee.android.Ex1020_002;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;public class Ex1020_002Activity extends ListActivity {
TextView _textView;
String _items[]={"유비","관우","장비","조조","조운","여포","제갈량","하후돈","하후연","곽가","능통","황충","초선"};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setListAdapter(new ImageAdapter());
_textView=(TextView)findViewById(R.id.textview);
}
protected void onListItemClick (ListView l, View v, int position, long id) {
_textView.setText(_items[position]);
}
class ImageAdapter extends ArrayAdapter {
ImageAdapter() {
super(Ex1020_002Activity.this, R.layout.row, _items);
}
// 방금 생성한 새로운 행은 고정된 레이아웃 파일에서 생성됐기 때문에 아무런 내용이 없다.
// 레이아웃에 따라 구성된 위젯에 프로그램이 갖고 있는 데이터를 채워 넣는 일을 getView()메소드가 한다.
public View getView(int position, View convertView, ViewGroup parent) {
// public abstract View getView(int position, View convertView, ViewGroup parent)// position : adapter의 data내의 item위치 정보를 알려줌.
// convertView : 이전의 재사용 되어지는 View 그리고 지금 View가 null인지 적절한 Type인지 확인해야 한다.
// 이전에 View가 없다면 새로운 view를 생성한다.
// parent : getview에 의해 접근되어질 view
LayoutInflate inflater = getLayoutinflater();// Layoutinflater를 실행한 결과로 View객체를 받아오는데 실제로 XML레이아웃에 들어 있는
// ImageView와 TextView를 갖는 LinearLayout클래스를 넘겨 받는다.
// public View inflate (int resource, ViewGroup root, boolean attachToRoot)
View row = inflater.inflate(R.layout.row, parent, false);// getView()메소드에서는 지정한 위치의 행을 표시할 View 클래스를 리턴 해야 한다.
TextView label = (TextView)row.findViewById(R.id.label);
label.setText(_items[position]);
label.setTextSize(30);
ImageView icon=(ImageView)row.findViewById(R.id.imageview);
// 각 행마다 다른 Image를 출력하기 위한 Switch문
switch(position) {
case 0:
icon.setImageResource(R.drawable.ubi);
break;
case 1:
icon.setImageResource(R.drawable.gwanwoo);
break;
case 2:
icon.setImageResource(R.drawable.jangbi);
break;
case 3:
icon.setImageResource(R.drawable.jojo);
break;
case 4:
icon.setImageResource(R.drawable.joun);
break;
case 5:
icon.setImageResource(R.drawable.yeopo);
break;
case 6:
icon.setImageResource(R.drawable.jaegal);
break;
case 7:
icon.setImageResource(R.drawable.hahudon);
break;
case 8:
icon.setImageResource(R.drawable.hahuyeon);
break;
case 9:
icon.setImageResource(R.drawable.gwakga);
break;
case 10:
icon.setImageResource(R.drawable.neungtong);
break;
case 11:
icon.setImageResource(R.drawable.hwangchung);
break;
default:
icon.setImageResource(R.drawable.chosun);
break;
}
return (row);
}
}}
// Ex1021_001Activity.java
// 이건 ListView 성능 향상 버전이다^^
package lee.android.Ex1021_001;
import android.app.ListActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;public class Ex1021_001Activity extends ListActivity {
TextView selection;
String items[]= {"유비","관우","장비","조조","조운","곽가","능통","여포","황충","하후연","하후돈","초선","제갈량"};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setListAdapter(new ImageAdapter());
selection=(TextView)findViewById(R.id.mainText);
}
private String getModel(int position) {
return (((ImageAdapter)getListAdapter()).getItem(position));
}
protected void onListItemClick (ListView l, View v, int position, long id) {
selection.setText(items[position]);
}
class ImageAdapter extends ArrayAdapter <String>{
ImageAdapter() {
super(Ex1021_001Activity.this, R.layout.row,items);
}
public View getView(int position, View convertView, ViewGroup parent) {
// convertView값이 null이 아니라면 그 값은 예전에 getView() 메소드에서 생성했던 View 인스턴스 가운데 하나다.
// 아래와 같이 구현을 하면 행별 위젯을 매번 생성하지 않아 CPU의 사용량이 줄어든다.
View row=convertView;
ViewWrapper wrapper=null;
if(row==null) {
LayoutInflater inflater = getLayoutInflater();
row= inflater.inflate(R.layout.row, parent, false);
// 만들어진 행이 없을 경우 ViewWrapper클래스를 새로 만들어 넣는다.
wrapper=new ViewWrapper(row);
row.setTag(wrapper);
Log.d("dodo4989", "row==null");
}
else {
// 이미 만들어진 행이 있을 경우 해당하는 행의 View 인스턴스에서 ViewWrapper인스턴스를 가져온다.
wrapper = (ViewWrapper)row.getTag();
Log.d("dodo4989", "row!=null");
}
wrapper.getLabel().setText(getModel(position));
switch(position) {
case 0 :
wrapper.getIcon().setImageResource(R.drawable.ubi);
break;
case 1 :
wrapper.getIcon().setImageResource(R.drawable.gwanwoo);
break;
case 2 :
wrapper.getIcon().setImageResource(R.drawable.jangbi);
break;
case 3 :
wrapper.getIcon().setImageResource(R.drawable.jojo);
break;
case 4 :
wrapper.getIcon().setImageResource(R.drawable.joun);
break;
case 5 :
wrapper.getIcon().setImageResource(R.drawable.gwakga);
break;
case 6 :
wrapper.getIcon().setImageResource(R.drawable.neungtong);
break;
case 7 :
wrapper.getIcon().setImageResource(R.drawable.yeopo);
break;
case 8 :
wrapper.getIcon().setImageResource(R.drawable.hwangchung);
break;
case 9 :
wrapper.getIcon().setImageResource(R.drawable.hahuyeon);
break;
case 10 :
wrapper.getIcon().setImageResource(R.drawable.hahudon);
break;
case 11 :
wrapper.getIcon().setImageResource(R.drawable.chosun);
break;
default :
wrapper.getIcon().setImageResource(R.drawable.jaegal);
break;
}
return (row);
}
}class ViewWrapper {
View base;
TextView label=null;
ImageView icon=null;
ViewWrapper(View base) {
this.base=base;
}
// findViewById()를 사용하면 원하는 객체를 얼마든 찾을 수 있으나 객체를 찾는데 필요한 연산의 양이// 많아 효율성이 떨어진다. Holder pattern을 이용하여 이를 해결 할 수 있다.
// View객체마다 setTag(), getTag() 메소드를 이용하여 나중에 사용할 내부 위젯을 캐시해두는 방법을 사용한다.
// 각 행의 View에 홀더 객체를 태그로 설정해 두고, 해당하는 행을 사용할 때는 필요한 내부 객에에 대한// 참조를 모두 갖고 있기 때문에 findViewById()메소드를 매번 호출할 필요가 없다.
TextView getLabel() {
if(label==null) {
label=(TextView)base.findViewById(R.id.rowText);
Log.d("dodo4989", "label==null");
}
return(label);
}
ImageView getIcon() {
if(icon==null) {
icon=(ImageView)base.findViewById(R.id.rowImage);
Log.d("dodo4989", "icon==null");
}
return(icon);
}
}}
Log cat의 내용은 아래와 같다.
처음 리스트를 가져올때만 생성을 하고, 그 뒤로는 캐시된 값을 이용하여 성능 향상을 가져온다.
10-21 08:36:57.061: DEBUG/dodo4989(3378): row==null
10-21 08:36:57.061: DEBUG/dodo4989(3378): label==null
10-21 08:36:57.072: DEBUG/dodo4989(3378): icon==null
10-21 08:36:57.242: DEBUG/dodo4989(3378): row==null
10-21 08:36:57.242: DEBUG/dodo4989(3378): label==null
10-21 08:36:57.242: DEBUG/dodo4989(3378): icon==null
10-21 08:36:57.322: DEBUG/dodo4989(3378): row==null
10-21 08:36:57.322: DEBUG/dodo4989(3378): label==null
10-21 08:36:57.322: DEBUG/dodo4989(3378): icon==null
10-21 08:37:05.202: DEBUG/dodo4989(3378): row==null
10-21 08:37:05.202: DEBUG/dodo4989(3378): label==null
10-21 08:37:05.202: DEBUG/dodo4989(3378): icon==null
10-21 08:37:06.720: DEBUG/dodo4989(3378): row==null
10-21 08:37:06.720: DEBUG/dodo4989(3378): label==null
10-21 08:37:06.720: DEBUG/dodo4989(3378): icon==null
10-21 08:37:09.031: DEBUG/dodo4989(3378): row!=null
10-21 08:37:10.512: DEBUG/dodo4989(3378): row!=null
10-21 08:37:10.761: DEBUG/dodo4989(3378): row!=null
10-21 08:37:10.881: DEBUG/dodo4989(3378): row!=null
10-21 08:37:10.992: DEBUG/dodo4989(3378): row==null
10-21 08:37:11.002: DEBUG/dodo4989(3378): label==null
10-21 08:37:11.026: DEBUG/dodo4989(3378): icon==null
10-21 08:37:11.651: DEBUG/dodo4989(3378): row!=null
10-21 08:37:11.781: DEBUG/dodo4989(3378): row!=null
10-21 08:37:11.911: DEBUG/dodo4989(3378): row!=null
10-21 08:37:17.601: DEBUG/dodo4989(3378): row!=null
10-21 08:37:17.660: DEBUG/dodo4989(3378): row!=null
10-21 08:37:17.731: DEBUG/dodo4989(3378): row!=null
'안드로이드 > List' 카테고리의 다른 글
ExpandableListView 예제 사이트 링크 (0) | 2011.02.22 |
---|---|
ListView 구분선 색상 조절하기. (0) | 2011.02.11 |
ListView 스크롤시 검은색 배경으로 바뀌는 문제 & Selector가 표시되지 않는 경우 (0) | 2011.02.11 |
[ListView] Ex 2. marquee (1) | 2011.02.11 |
[ListView] 사진과 marquee tag를 사용한 ListView Source (1) | 2011.02.11 |