Notice
Recent Posts
Recent Comments
Link
관리 메뉴

설.현.아빠

[ListView] Image+Text 성능 향상 버전 포함. 본문

안드로이드/List

[ListView] Image+Text 성능 향상 버전 포함.

설.현.아빠 2011. 2. 11. 10:48




 

<?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

 


Comments