2012-04-22 1 views
7

나는 Commonsware 안드로이드 프로그래밍 튜토리얼과 튜토리얼 5, 여분의 크레딧 2를 통해 작업 해왔다. 도전 과제는 객체의 "유형 이름"에 따라 ListView에 행을 표시하기 위해 다중 레이아웃을 사용하는 것이다 (레스토랑의 유형 "속성, String). 따라서 사용자 지정 ArrayAdapter에서 getItemViewTypegetViewTypeCount을 재정의 할 것을 제안합니다. 또한 android docs 및 기타 online recipes 또는 blog posts도 마찬가지입니다.레시피가 왜 보이지 않는 경우 getItemViewType 및 getViewTypeCount를 재정의하는 것을 권장합니까?

이러한 상황에서이 제조법을 따르고이 두 가지 방법을 무시하면 해당 레스토랑의 "type"속성 값을 검사하여 중복 로직이 발생합니다.

class RestaurantsAdapter extends ArrayAdapter<Restaurant> { 

    private static final int ROW_TYPE_DELIVERY = 0; 
    private static final int ROW_TYPE_TAKE_OUT = 1; 
    private static final int ROW_TYPE_SIT_DOWN = 2; 

    RestaurantsAdapter() { 
    super(LunchListActivity.this, android.R.layout.simple_list_item_1, restaurants); 
    } 

    public int getViewTypeCount() { 
    return 3; 
    } 

    public int getItemViewType(int position) { 
    String type = restaurants.get(position).getType(); 
    if (type == "delivery") { 
     return ROW_TYPE_DELIVERY; 
    } else if (type == "take_out") { 
     return ROW_TYPE_TAKE_OUT; 
    } else { 
     return ROW_TYPE_SIT_DOWN; 
    } 
    } 

    // Sets the icon, name and address of the Restaurant for the view. 
    public View getView(int position, View convertView, ViewGroup parent) { 
    View row = convertView; 
    RestaurantHolder viewHolder; 

    if (row == null) { 
     LayoutInflater inflater = getLayoutInflater(); 
     switch (getItemViewType(position)) { 
     case ROW_TYPE_DELIVERY: 
      row = inflater.inflate(R.layout.row_delivery, null); 
      break; 
     case ROW_TYPE_TAKE_OUT: 
      row = inflater.inflate(R.layout.row_take_out, null); 
      break; 
     default: 
      row = inflater.inflate(R.layout.row_sit_down, null); 
      break; 
     } 

     viewHolder = new RestaurantHolder(row); 
     row.setTag(viewHolder); 
    } else { 
     viewHolder = (RestaurantHolder)row.getTag(); 
    } 

    viewHolder.populateFrom(restaurants.get(position)); 

    return row; 
    } 

} 

나 중복 로직합니다 (경우/다른 getItemViewType을에서 무엇 버그 : 예를 들어 (이 어댑터는 내부 클래스이고 restaurants가 외부 활동의 멤버로 선언 레스토랑 오브젝트의 ArrayList를 대상이므로주의) getViewswitch). 그래서, 내가 다음에 내 구현을 변경 :이 동적으로 세 가지 XML 레이아웃 중 하나를로드하는 목표를 달성 중복 로직을 제거

class RestaurantsAdapter extends ArrayAdapter<Restaurant> { 

    RestaurantsAdapter() { 
    super(LunchListActivity.this, android.R.layout.simple_list_item_1, restaurants); 
    } 

    // Sets the icon, name and address of the Restaurant for the view. 
    public View getView(int position, View convertView, ViewGroup parent) { 
    View row = convertView; 
    RestaurantHolder viewHolder; 

    if (row == null) { 
     LayoutInflater inflater = getLayoutInflater(); 
     if (restaurants.get(position).getType() == "delivery") { 
     row = inflater.inflate(R.layout.row_delivery, null); 
     } else if (restaurants.get(position).getType() == "take_out") { 
     row = inflater.inflate(R.layout.row_take_out, null); 
     } else { 
     row = inflater.inflate(R.layout.row_sit_down, null); 
     } 
     viewHolder = new RestaurantHolder(row); 
     row.setTag(viewHolder); 
    } else { 
     viewHolder = (RestaurantHolder)row.getTag(); 
    } 

    viewHolder.populateFrom(restaurants.get(position)); 

    return row; 
    } 

} 

, 약간 레이아웃의 수에 코드의 결합을 줄이고, 필요로하지 않습니다 getViewTypeCountgetItemViewType보다 우선합니다.

내 질문은 : 왜 두 가지 방법 중 하나를 사용해야합니까?

답변

16

왜 두 가지 방법을 무시해야합니까?

위에 표시된 구현을 고려할 때 수십 개의 레스토랑과 다양한 유형의 레스토랑을 추가하고 스크롤 할 때 행 재활용이 달라 지는지 지켜보십시오.

getItemViewType()getViewTypeCount()은 행 재활용을 보장합니다. 안드로이드는 별도의 객체 풀을 유지하며 올바른 유형의 재활용을 위해 행을 돌려 줄 것입니다.

해결책으로는 R.layout.row_delivery 행을 부풀린 다음 나중에 실제로 R.layout.row_sit_down 행이 필요할 때 재활용을 위해 다시 돌려받을 수 있습니다.

참고 사항 : AdapterView에는 inflate(R.layout.row_take_out, null)을 사용하지 마십시오. RelativeLayout 규칙을 올바르게 처리하려면 inflate(R.layout.row_take_out, parent, false)을 사용하십시오.

+0

감사 마크; 나는 의심의 여지가 재활용에 대한 깊은 이해가 부족하기 때문이라고 생각했다. – ybakos

+0

@ybakos : Warescription을 갖고 있다면, "List with Fancy with Lists"장을 읽고 재활용에 대한 자세한 내용을 읽어보십시오. – CommonsWare