Search code examples
javaandroidsqlitearraylistandroid-cursoradapter

ArrayList<String> is not working properly in CursorAdapter


I am trying to get database from SQLite database and trying to populate the ListView and also adding data in ArrayList<String> . The ListView is populated nicely but problem is ArrayList<String> is not populated nicely.

Suppose I have data in database like: A B C D E F G H I J K L M N ........ My ListView Showing data in this way. But ArrayList<String> add the data this way: A B C D E F A B C D E F G H ......

That means my ArrayList<String> takes first 6 value then repeat it and then it takes next 6 value then again repeat it ..... . That means When I click item "H" from list view the ArrayList<String> shows me "B". I don't know why it is happening?

My Code, CustomList which extends CursorAdapter

import java.util.ArrayList;

import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CursorAdapter;
import android.widget.TextView;

public class CustomList extends CursorAdapter {

    CheckBox favoriteBox;
    TextView cityName, countryName;
    ArrayList<String> city_name;
    ArrayList<String> country_name;
    ArrayList<String> country_short;
    ArrayList<CheckBox> check_box;

    public CustomList(Context context, Cursor c, ArrayList<String> city_name,
            ArrayList<String> country_name, ArrayList<String> country_short,
            ArrayList<CheckBox> check_box) {
        super(context, c, 0);
        this.city_name = city_name;
        this.country_name = country_name;
        this.country_short = country_short;
        this.check_box = check_box;
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {

        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View retView = inflater.inflate(R.layout.all_city_list, parent, false);

        return retView;
    }

    @Override
    public void bindView(final View view, Context context, Cursor cursor) {
        cityName = (TextView) view.findViewById(R.id.cityName);
        String cityS = cursor.getString(cursor.getColumnIndex("city_name"));
        cityName.setText(cityS);
        city_name.add(cityS);//adding value to ArrayList<String>

        countryName = (TextView) view.findViewById(R.id.countryName);
        String conS = cursor.getString(cursor.getColumnIndex("country_name"));
        countryName.setText(conS);
        country_name.add(conS);//adding value to ArrayList<String>
        country_short.add(""
                + cursor.getString(cursor.getColumnIndex("country_short")));//adding value to ArrayList<String>

        favoriteBox = (CheckBox) view.findViewById(R.id.favoriteCheckBox);
        check_box.add(favoriteBox);
        if (cursor.getInt(cursor.getColumnIndex("favorite")) == 0) {
            favoriteBox.setChecked(false);
        } else {
            favoriteBox.setChecked(true);
        }
    }
}

Class AllCityListFragment which extends Fragment

import java.io.IOException;
import java.util.ArrayList;

import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.Toast;

public class AllCityListFragment extends Fragment {
    private CustomList customAdapter;
    private DatabaseHelper databaseHelper;
    ArrayList<String> city_name = new ArrayList<String>();
    ArrayList<String> country_name = new ArrayList<String>();
    ArrayList<String> country_short = new ArrayList<String>();
    ArrayList<CheckBox> check_box = new ArrayList<CheckBox>();

    public static final String ARG_OS = "OS";
    int pos;
    String sql = "";

    ListView list;
    View view;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.all_city_layout, null);

        databaseHelper = new DatabaseHelper(view.getContext());

        try {
            databaseHelper.createDataBase();
            databaseHelper.openDataBase();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            Toast.makeText(view.getContext(), "Error: " + e.getMessage(),
                    Toast.LENGTH_LONG).show();
            e.printStackTrace();
        }

        list = (ListView) view.findViewById(R.id.citylist);
        list.setFocusable(false);

        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View myview,
                    int position, long id) {
                Toast.makeText(getActivity(),
                        position + " " + city_name.get(position),
                        Toast.LENGTH_LONG).show();
            }
        });

            sql = "SELECT _id, city_name, country_name, country_short, favorite FROM city order by country_name asc;";


        new Handler().post(new Runnable() {
            @Override
            public void run() {
                customAdapter = new CustomList(getActivity(), databaseHelper
                        .getResult(sql), city_name, country_name,
                        country_short, check_box);

                list.setAdapter(customAdapter);
            }
        });

        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }


}

enter image description here

In this picture I clicked "Shirajganj" but the Toast shows me "230 Thakurgaon" position =230 is correct but city_name.get(230) should be "Shirajganj" . I think it is doing wrong when I am trying to add value to ArrayList<String> in binView in CustomList. How can I solve this problem?


Solution

  • It's not a good idea to fill that array in bindView method. The Android doesn't create separate view for each row in the list, it's utilize already created ones, that's why you will always receive unexpected results in your arraylist. The better is to fill the array in your activity, instead of the adapter. Just query your database for the same result like this:

    Cursor cursor = getContentResolver().query(
        uri,  
        projection,                       
        selectionClause                   
        selectionArgs,                    
        sortOrder);   
    
    while (cursor.moveToNext ()){
        arrayList.add(cursor.getAsString(cursor.getColumnIndex('column_name')));
    }
    cursor.close()