ListAdapter. getView return bad link of item from View(convertView)

37 Views Asked by At

I had a strange error with ListAdapter(ArrayAdapter). I solved this problem, but I think, that anybody can have some problem and I decided to write about my solution.

My task: ListView, that has onclick events from each item. Last selected item (its _id val) save into SharedPreferences. After reopening Activity need to load last selected item position (use saved _id in SharedPreferences).

Problem: After the component is loading I had more times called getView with other view's value (null or not null) and position (several times the position value was 0). But the main problem is get link from selected item.

My code:

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; have bad link, although the code is correct and the condition (i == MainActivity.idProgram) is on only suitable for one option. But After I clicked other item and after running the line of code beforeHolder.frontView.setBackgroundResource(R.color.colorAccent); the item color not changed.

1

There are 1 best solutions below

1
Alex On

After spending a couple of days, I found a way out from the situation. I understood that the error was in Activity layout. I set the parameter layout_height="wrap_content" to the ListView and because for this getView running more times (I added the same component several times, as it was changing its size during the process of adding).

In first I added line

ProgramActivity.adapter.notifyDataSetChanged();

(In the code, it is commented out.) and deleted beforeHolder = holder; into condition (i == MainActivity.idProgram), but this solution at the first click had a delay of about 1 second.

The favorite solution is change layout_height to fill_parent. In conclusion, I would like to say that this is some kind of bug, and even with wrap_content, the beforeHolder variable should have a valid reference.