How can I eliminate the dependency from of a ListView's onItemClick/getView and its row types?

血红的双手。 提交于 2019-12-11 18:05:23

问题


As a simplified example, consider a ListView that can contain both sub-categories and book titles. If a book title is clicked, a new activity should start that shows the cover image. If a sub-category is clicked, a new list of books and categories is displayed.

A Row interface is defined as follows.

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

I would like to know how to prevent a dependency from the ListView's ArrayAdapter as well as from the implementer of onItemClickListener on the Row implementers (e.g.,Book and Category).

One of the forces driving this requirement is the "don't repeat yourself" (DRY) principle: the ArrayAdapter implementation does not need to change when new row types are introduced.


回答1:


Forgive my chicken-scratched "UML" below, but here's how I do it.

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;
    }
}

The implementer of OnItemClickListener has a method like this:

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

Then RowProvider has a method like this:

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

Then the Row interface has a method with signature void onClick() and there are Category and Book implementations of Row that provide the necessary behavior.




回答2:


Another possibility is to use the setTag/getTag methods on each item's View in the list - this allows you to attach the 'Book' or 'Category' to its appropriate row.

For this to work each of the 'listed' items should implement a common interface that has an appropriate method to be called when it is clicked.

For instance:

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

In your list adapter:

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 );
}

Then when an item is clicked:

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...
   }
}

A bit more detail on the setTag method: setTag documentation

Hope this helps...



来源:https://stackoverflow.com/questions/9721790/how-can-i-eliminate-the-dependency-from-of-a-listviews-onitemclick-getview-and

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!