ListAdapter.getView возвращает неверную ссылку на элемент из View (convertView) - PullRequest
0 голосов
/ 22 мая 2019

У меня была странная ошибка с ListAdapter (ArrayAdapter).Я решил эту проблему, но думаю, что у кого-то может быть какая-то проблема, и я решил написать о своем решении.

Моя задача: ListView, в котором есть события onclick для каждого элемента.Последний выбранный элемент (его _id val) сохраните в SharedPreferences.После повторного открытия Activity нужно загрузить последнюю выбранную позицию элемента (используйте сохраненный _id в SharedPreferences).

Проблема: После загрузки компонента я несколько раз вызывал getView со значением другого представления (нулевым или не нулевым) и позицией (несколько раз значение позиции было 0).Но главная проблема - получить ссылку из выбранного элемента.

Мой код:

public class ListAdapter extends ArrayAdapter<String[]> {
private final LayoutInflater mInflater;
private final ViewBinderHelper binderHelper;
public ViewHolder beforeHolder = null;

public ListAdapter(Context context, List<String[]> objects) {
    super(context, R.layout.lv_item, objects);
    mInflater = LayoutInflater.from(context);
    binderHelper = new ViewBinderHelper();
}

public  int a = 0;
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;

    int i = Integer.valueOf(ProgramActivity.dirNames.get(position));
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.lv_item, parent, false);

        holder = new ViewHolder();
        holder.swipeLayout = (SwipeRevealLayout) convertView.findViewById(R.id.swipe_layout);
        holder.frontView = convertView.findViewById(R.id.front_layout);
        holder.textView = (TextView) convertView.findViewById(R.id.text);


        holder.frontView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (backStack.size() > 0) {
                    Toast.makeText(getContext(), "У вас уже выбрана последовательность программ", Toast.LENGTH_SHORT).show();
                    return;
                }

                if (beforeHolder != null) {
                    beforeHolder.frontView.setBackgroundResource(R.color.colorAccent);
                }
                else {
                    //ProgramActivity.adapter.notifyDataSetChanged();
                }

                view.setBackgroundResource(R.color.holo_green_light);

                SharedPreferences.Editor ed = MainActivity.sPref.edit();
                ed.putInt("idProgram",holder.idProgram);
                ed.commit();

                MainActivity.idProgram = holder.idProgram;

                beforeHolder = holder;
            }
        });


        convertView.setTag(holder);

    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    final String[] item = getItem(position);
    if (item != null) {
        holder.idProgram = i;
        if (i == MainActivity.idProgram) {
            holder.frontView.setBackgroundResource(R.color.holo_green_light);
            beforeHolder = holder;
        } else {
            holder.frontView.setBackgroundResource(R.color.colorAccent);
        }

        binderHelper.bind(holder.swipeLayout, item[1]);

        holder.textView.setText(item[1]);
    }

    return convertView;
}

/**
 * Only if you need to restore open/close state when the orientation is changed.
 * Call this method in {@link android.app.Activity#onSaveInstanceState(Bundle)}
 */
public void saveStates(Bundle outState) {
    binderHelper.saveStates(outState);
}

/**
 * Only if you need to restore open/close state when the orientation is changed.
 * Call this method in {@link android.app.Activity#onRestoreInstanceState(Bundle)}
 */
public void restoreStates(Bundle inState) {
    binderHelper.restoreStates(inState);
}

private class ViewHolder {
    SwipeRevealLayout swipeLayout;
    View frontView;
    TextView textView;
    int idProgram;
}
}

beforeHolder = holder;имеют неверную ссылку, хотя код правильный и условие (i == MainActivity.idProgram) включено только для одной опции.Но после того, как я щелкнул другой элемент и после запуска строки кода beforeHolder.frontView.setBackgroundResource (R.color.colorAccent);Цвет товара не изменился.

1 Ответ

0 голосов
/ 22 мая 2019

Потратив пару дней, я нашел выход из ситуации.Я понял, что ошибка была в макете деятельности.Я установил для параметра layout_height="wrap_content" значение ListView и потому, что для этого getView работает больше раз (я добавлял один и тот же компонент несколько раз, так как он изменял свой размер в процессе добавления).

В первую очередьЯ добавил строку

ProgramActivity.adapter.notifyDataSetChanged();

(в коде это закомментировано.) И удалил beforeHolder = holder; в условие (i == MainActivity.idProgram), но это решение при первом клике имело задержкуоколо 1 секунды.

Любимое решение - изменить layout_height на fill_parent.В заключение я хотел бы сказать, что это какая-то ошибка, и даже с wrap_content переменная beforeHolder должна иметь действительную ссылку.

...