Как я могу устранить зависимость от onItemClick / getView ListView и его типов строк? - PullRequest
0 голосов
/ 15 марта 2012

В качестве упрощенного примера рассмотрим ListView, который может содержать как подкатегории, так и названия книг.Если щелкнуть название книги, должно начаться новое действие с изображением обложки.При щелчке по подкатегории отображается новый список книг и категорий. Интерфейс

A Row определяется следующим образом.

interface Row {
   void onClick();
   void draw(View v);
}

Я хотел бы знать, как предотвратить зависимость от ListView ArrayAdapter, а также от реализации onItemClickListener на реализациях Row (например, Book и Category).

Одной из движущих сил этого требования является принцип "не повторяйся" (СУХОЙ): реализация ArrayAdapter не должна изменяться при введении новых типов строк.

Ответы [ 2 ]

1 голос
/ 15 марта 2012

Простите за мой поцарапанный "UML" ниже, но вот как я это делаю.

class ListAdapter extends ArrayAdapter<Row<?>> {
...
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = listViewRowViewRecycler.getView(convertView);
        rowProvider.get().getRow(position).draw(view);
        return view;
    }
}

Реализатор OnItemClickListener имеет такой метод:

void onItemClick(AdapterView<?> adapterView, View view, int rowIndex, long rowId)
{
   rowProvider.onItemClick(rowIndex);
}

Тогда RowProvider имеет такой метод:

void onItemClick(int rowIndex) {
    rowList.get(rowIndex).onClick();
}

Тогдаинтерфейс Row имеет метод с сигнатурой void onClick(), и существуют Category и Book реализации Row, которые обеспечивают необходимое поведение.

UML Diagram

0 голосов
/ 15 марта 2012

Другой возможностью является использование методов setTag / getTag для каждого элемента View в списке - это позволяет вам присоединить 'Book' или 'Category' к соответствующей строке.

Для того, чтобы это работало каждый«перечисленные» элементы должны реализовывать общий интерфейс, который имеет соответствующий метод, который вызывается при нажатии.

Например:

interface Selectable {
    void onSelected();  // Add parameters if necessary...
}

В вашем адаптере списка:

public View getView(int position, View convertView, ViewGroup parent) {    
    View itemView;  // Logic to get the appropriate view for this row.

    Selectable theObjectBeingRepresented;
    //
    // Logic to assign a Book/Category, etc to theObjectBeingRepresented.
    // In this example assume there is a magic Book being represented by 
    // this row.
    //
    Book aMagicBook = new Book();
    theObjectBeingRepresented = aMagicBook;

    // If all objects that will be contained in your list implement the 
    // 'Selectable' interface then you can simply call setTag(...) with
    // the object you are working with (otherwise you may need some conditional logic)
    //
    itemView.setTag( SELECTABLE_ITEM_KEY, theObjectBeingRepresented );
}

Затем при нажатии на элемент:

void onItemClick(AdapterView<?> adapterView, View view, int rowIndex, long rowId) 
{ 
   Selectable item = (Selectable)view.getTag( SELECTABLE_ITEM_KEY );

   // Depending on how you are populating the list, you may need to check for null
   // before operating on the item..
   if( null != item ) {
       item.onClick();  // Appropriate implementation called...
   }
}

Немного подробнее о методе setTag: Документация по setTag

Надеюсь, это поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...