为性能而设计的自定义列表数组适配器:在哪里添加侦听器?

时间:2014-12-21 14:41:31

标签: android performance listadapter

我已经编写了一个自定义列表视图数组适配器,推荐的模式表明我们应该在getView()方法中使用ViewHolder以获得性能(和电池?)。我遇到麻烦的地方是我应该在哪里添加监听器到我的复选框组件。在listview适配器源文件之后我会更明确:

package com.loloof64.android.chess_position_manager.file_explorer;

// all my importes (eluded)

public class FilesListArrayAdapter extends ArrayAdapter<ListFileElement> {

    private final Context context;
    private final ArrayList<ListFileElement> elements;
    private final ArrayList<ListFileElement> selectedElements = new ArrayList<>();
    private boolean isSelectionMode = false;

    public FilesListArrayAdapter(Context context, ListFileElement[] objects) {
        super(context, R.layout.file_list_view, objects);
        this.context = context;
        this.elements = new ArrayList<>(Arrays.asList(objects));
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = convertView;

        // reuse views
        if (rowView == null){
            LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            rowView = inflater.inflate(file_list_view, parent, false);

            // configure view holder
            FileItemViewHolder viewHolder = new FileItemViewHolder();
            viewHolder.checkBoxView = (CheckBox) rowView.findViewById(R.id.file_list_item_checkbox);
            viewHolder.nameView = (TextView) rowView.findViewById(R.id.file_list_item_name);
            viewHolder.iconView = (ImageView) rowView.findViewById(R.id.file_list_item_icon);

            // **** 1 *****
            // Should I add item listeners here ?

            rowView.setTag(viewHolder);
        }

        // fill data
        FileItemViewHolder viewHolder = (FileItemViewHolder) rowView.getTag();
        ListFileElement bindedElement = elements.get(position);
        viewHolder.nameView.setText(bindedElement.getFileName());

        // **** 2 *****
        // Should I rather add item listeners here ?

        viewHolder.checkBoxView.setVisibility(isSelectionMode ? View.VISIBLE : View.GONE);
        viewHolder.checkBoxView.setClickable(ListFileElement.PARENT_DIR != bindedElement);

        if (bindedElement.isDirectory()){
            viewHolder.iconView.setImageResource(R.drawable.ic_folder);
        }
        else {
            viewHolder.iconView.setImageResource(R.drawable.ic_file);
        }

        return rowView;
    }

    public boolean isSelectionMode() {
        return isSelectionMode;
    }

    public void toggleSelectionMode(){
        isSelectionMode = !isSelectionMode;
    }

    public ListFileElement[] getSelectedElements(){
        return selectedElements.toArray(new ListFileElement[0]);
    }
}

当然,为了理解我的问题,不需要ListFileElement源代码。 您应该已经注意到我的源文件的代码注释中的部分**** 1 *****和**** 2 ****。

让我遇到麻烦的是项目加载效率和程序正确性(没有错误):在ViewHolder(第1部分)中添加控件或在每个项目视图加载(第2部分)之后,我应该添加项目复选框监听器吗?

1 个答案:

答案 0 :(得分:1)

创建行时,您可以设置一次侦听器。但是,一旦您需要某种方式知道(在侦听器内)单击了什么,请设置它们。为此,您必须在绑定视图时指定行所属的元素。类似的东西应该有效:

// reuse views
if (rowView == null){
    ...
    // **** 1 *****
    viewHolder.checkboxView.setOnClickListener(new View.OnClickListener() {
         public void onClick(View v) {
             Checkbox cb = (Checkbox) v;
             int position = (Integer)v.getTag();
             ListFileElement bindedElement = getItem(position);
             if (cb.isChecked()) {
                 // Do something
             } else {
                 // Do something else
             }
         }
     });
    rowView.setTag(viewHolder);
}

// Bind the view
viewHolder.checkboxView.setTag(position);

由于您在绑定视图时将项目的位置设置为复选框上的标记,因此复选框单击侦听器可以简单地从复选框标记中获取该位置并获取对该项目的引用。

或者,您只需将项目设置为标记,而不是位置参考!