Home > OS >  List view is not loading records correctly from some point
List view is not loading records correctly from some point

Time:05-18

I have an scrollable list to which I am adding some records dynamically. It works very simple, I add records to ArrayList, than pass it to adapter. The problem is when I am scrolling, 3 first records always get loaded, than during scrolling first few records also gets loaded. But later i keep getting some random previous records (seems like according to the ArrayList which is correct). How can I force records to be loaded? I also read in other's articles that initializing layout="match_parent" could help, which I have done. I'm posting my code below.

public void addItem(String item) {
      assets.add(0, item);
      listView.setAdapter(adapter);
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity">


    <ListView
        android:id="@ id/list_view"
        android:layout_width="match_parent"
        android:paddingRight="0sp"
        android:layout_height="350dp" />

    <Button
        android:id="@ id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@ id/list_view"
        android:onClick="save"
        android:layout_marginLeft="24dp"
        android:text="Zapisz"
        android:backgroundTint="@color/colorPrimary"/>

My custom adapter class:

public class ListViewAdapter extends ArrayAdapter<String> {
    ArrayList<String> list;
    Context context;

    public ListViewAdapter(Context context, ArrayList<String> items) {
        super(context, R.layout.list_row, items);
        this.context = context;
        list = items;
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            LayoutInflater mInflater = LayoutInflater.from(context);
            convertView = mInflater.inflate(R.layout.list_row, parent, false);
            TextView name = convertView.findViewById(R.id.name);
            ImageView remove = convertView.findViewById(R.id.remove);
            name.setText(list.get(position));
            
            
            remove.setOnClickListener(view -> MainActivity.removeItem(position));
        }
        return convertView;
    }
}

list_row.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="15sp">

    <TextView
        android:id="@ id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:textColor="#000"
        android:textSize="20sp"
        android:layout_marginRight="30sp"/>

    <ImageView
        android:id="@ id/remove"
        android:layout_width="22sp"
        android:layout_height="22sp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="6sp"
        android:src="@drawable/remove" />

</RelativeLayout>

CodePudding user response:

Update your getView() method like below, No need to reassign convertview when it is not null but you need to set new values to that position.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = LayoutInflater.from(context).inflate(R.layout.list_row, parent, false);
    }
    TextView name = convertView.findViewById(R.id.name);
    ImageView remove = convertView.findViewById(R.id.remove);
    name.setText(list.get(position));
    remove.setOnClickListener(view -> MainActivity.removeItem(position));
    return convertView;
}

CodePudding user response:

Your adapter's getView() is called for each row. However, convertView will only be null for the first n views. After that, they are reused. Move your data population outside of the if so that it is guaranteed to be called for every row.

You should also consider using a RecyclerView instead to improve performance. findViewById is fairly expensive and the ViewHolder pattern can make scrolling smoother.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        LayoutInflater mInflater = LayoutInflater.from(context);
        convertView = mInflater.inflate(R.layout.list_row, parent, false);
    }

    TextView name = convertView.findViewById(R.id.name);
    ImageView remove = convertView.findViewById(R.id.remove);
    name.setText(list.get(position));
    remove.setOnClickListener(view -> MainActivity.removeItem(position));

    return convertView;
}
  • Related