Search code examples
androidandroid-listviewandroid-custom-viewcustom-lists

Dynamic CustomListView not getting updated


I implemented a custom list view using customadapter. When I press on refresh button, the data is fetched from database and updated in list view. But in my case the items get appended after the previous items i.e. if i have 2 items in databse and I press refresh button without changing the database items,the same items gets appended and 4 listitems get displayed. Quick help required. notifyDatasetChanged() is used in code. But I don't know if it's correct.

Here is code for MainActivity.java

public class MainActivity extends Activity {

ListView lv;

TextView tv1,tv2,tv3;
ArrayList<String> a=new ArrayList<String>();
ArrayList<String> b=new ArrayList<String>();
ArrayList<String> c=new ArrayList<String>();
ArrayList<String> d=new ArrayList<String>();
String mydata,name,name1,society,date,venue;
public String[] s1 = new String[50];
public String[] s2=new String[50];
public String[] s3=new String[50];
public String[] s4=new String[50];
public int[] img = {R.drawable.rty, R.drawable.sf, R.drawable.rty};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    tv1=(TextView)findViewById(R.id.textView);
    lv = (ListView) findViewById(R.id.listView);
    ConnectionDetector cd = new ConnectionDetector(getApplicationContext());
    Boolean isInternetPresent = cd.isConnectingToInternet(); // true or false

    if(isInternetPresent) {
        new MyData().execute();
    }
    else
    Toast.makeText(MainActivity.this,"No Internet Connection",Toast.LENGTH_SHORT).show();
    lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

            Intent in = new Intent(MainActivity.this, listclick.class);
            in.putExtra("position", position);
            startActivity(in);

        }
    });
}
public void abc(View v)
{
    Intent in=new Intent(MainActivity.this,webform.class);
    startActivity(in);

}
public void ref(View v)
{
    ConnectionDetector cd = new ConnectionDetector(getApplicationContext());
    Boolean isInternetPresent = cd.isConnectingToInternet();
    if(isInternetPresent) {



        new MyData().execute();

    }
    else
        Toast.makeText(MainActivity.this,"No Internet Connection",Toast.LENGTH_SHORT).show();

}
public class MyData extends AsyncTask<String,String,String>
{
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        CustomAdapter cad = new CustomAdapter(MainActivity.this, s1, img,s2,s3,s4);
        lv.setAdapter(cad);
        cad.notifyDataSetChanged();
    }

    @Override
    protected String doInBackground(String... params) {
        getData();
        return null;
    }
}

public void getData()
{
    try {
        HttpClient httpClient=new DefaultHttpClient();

        HttpPost httpPost=new HttpPost("http://collegeevents.esy.es/abc.php");
        HttpResponse response=httpClient.execute(httpPost);
        HttpEntity httpEntity=response.getEntity();
        InputStream is=httpEntity.getContent();
        BufferedReader reader=new BufferedReader(new InputStreamReader(is,"utf-8"),8);
        StringBuilder strbuilder=new StringBuilder();
        String line=null;
        while ((line=reader.readLine())!=null)
        {
            strbuilder.append(line);
        }
        is.close();
        mydata=strbuilder.toString();
        JSONArray obj=new JSONArray(mydata);
        for(int i=0;i<obj.length();i++)
        {

            JSONObject obj1=obj.getJSONObject(i);
            a.add(i,obj1.getString("Name"));
            b.add(i,obj1.getString("society"));
            c.add(i,obj1.getString("venue"));
            d.add(i,obj1.getString("date"));
        }
        String[] s = new String[a.size()];
        s=a.toArray(s);
        s1 = s;

        String[] soc = new String[b.size()];
        soc=b.toArray(soc);
        s2 = soc;

        String[] ven = new String[c.size()];
        ven=c.toArray(ven);
        s3 = ven;

        String[] dat = new String[d.size()];
        dat=d.toArray(dat);
        s4 = dat;
    }
    catch (Exception e)
    {

    }


}


}

Here is CustomAdapter.java

public class CustomAdapter extends ArrayAdapter<String> {

Context c1;
String s1[],soc[],ven[],dat[];
int s2[];
CustomAdapter(Context c,String s[],int s3[],String society[],String venue[],String date[])
{
    super(c, R.layout.listcustom, s);
    this.c1=c;
    this.s1=s;
    this.s2=s3;
    this.soc=society;
    this.ven=venue;
    this.dat=date;
}


@Override
public View getView(int position, View v, ViewGroup parent) {
    LayoutInflater li=(LayoutInflater) c1.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    v=li.inflate(R.layout.listcustom,parent,false);
    TextView tv=(TextView)v.findViewById(R.id.textView);
    TextView tv1=(TextView)v.findViewById(R.id.society);
    TextView tv2=(TextView)v.findViewById(R.id.venue);
    TextView tv3=(TextView)v.findViewById(R.id.date);
    tv.setText(s1[position]);
    tv1.setText(soc[position]);
    tv2.setText(ven[position]);
    tv3.setText(dat[position]);

    if(position%2==0) {
        tv.setTextColor(Color.parseColor("#01579B"));
        tv3.setTextColor(Color.parseColor("#01579B"));

    }
    else{
        tv.setTextColor(Color.parseColor("#00897B"));
        tv3.setTextColor(Color.parseColor("#00897B"));

    }

    v.setTag(position);
    //notifyDataSetChanged();
    return v;
}
}

Solution

  • I finally got it. The short answer for you question — you are not clearing a, b, c, d ArrayLists. So each getData() call adds data while previous data is still there. So, you should add a.clear(), b.clear() ... etc. at the start of getData.

    However i would suggest to make the following improvements:

    1. Introduce entity for adapter data. This entity will contain 4 fields: name, society, venue, date. Thus you don't need to use 4 arrays and 4 ArrayLists. For convience i will use "Event" as entity name. This will lok something like:

    AsyncTask:

    public class MyData extends AsyncTask<String, String, Event[]> {
        @Override
        protected Event[] doInBackground(String... params) {
            return getData();            
        }
        @Override
        protected void onPostExecute(Event[] s) {
            cad.clear();
            cad.addAll(s)
        }
    }
    

    Activity:

    public class MainActivity extends Activity {
        private CustomAdapter cad;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            ...
            lv = (ListView) findViewById(R.id.listView);
            cad = new CustomAdapter(getApplicationContext());
        }
    }
    

    CustomAdapter:

    public class CustomAdapter extends ArrayAdapter<Event> {
        private final LayoutInflater inflater;
        public CustomAdapter(Context c, Event ev[]) {
            super(context, ev[]);
            inflate = LayoutInflater.from(context);
        }
    
        CustomAdapter(Context c) {
            this(context, new Event[0]);
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final View v;
            if(convertView == null) {
                v = inflater.inflate(...)
            } else {
                v = convertView;
            }
    
            // find views or event better — use ViewHolder pattern
    
            Event evt = getItem(position);
            tv.setText(evt.getName());
            ...
    
            return v;
        }
    }
    
    1. Don't use onClick tag. Use view#setOnClickListener instead. onClick binds layout and activity implementation and that's not good.

    2. Use clear names. Something like LoadDataTask instead of MyData.