滚动时在自定义listView中显示数据时出错

时间:2013-02-12 07:28:39

标签: android android-listview

我向学者致敬。我对自定义列表视图感到很尴尬。在滚动时,我在listview中显示的值会发生变化。点击任何listitem,它会显示当前可见的第一条记录的数据。请帮帮我。我不知道如何处理 getView()方法来纠正这个错误。

我的java代码:

package com.addictioncounterapp;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class StartActivity extends Activity
{
ListView listview1;
static SQLiteDatabase database;
private Addiction[] addictions;
private ArrayAdapter<Addiction> listAdapter ;
ArrayList<Addiction> addictionList;
ImageView iv_settings;
static int limit;
static String attribute;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_start);

    createDB();
    loadDB();

    iv_settings = (ImageView) findViewById(R.id.imageViewStart);
    iv_settings.setOnClickListener(new OnClickListener()
                                        {
                                            @Override
                                            public void onClick(View v)
                                            {
                                                Intent intent = new Intent(StartActivity.this, Settings.class);
                                                startActivity(intent);
                                            }
                                        }
                                    );

    manageList();

    listview1 = (ListView) findViewById(R.id.listViewStart);
    if(addictionList.isEmpty())
    {
        Toast.makeText(getBaseContext(), "No records of Addiction found...Go to 'Settings > Manage Addictions > Add' to create new addiction.", Toast.LENGTH_LONG).show();
    }
    else
    {
        listview1.setAdapter(listAdapter);
    }

    listview1.setOnItemClickListener(new OnItemClickListener()
                                        {
                                            @Override
                                            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
                                            {
                                                View parentView = (View) arg1.getParent();
                                                String textview1 = ((TextView) parentView.findViewById(R.id.textViewStartAddictionName)).getText().toString();

                                                Intent intent = new Intent(StartActivity.this, AddictionDetails.class);
                                                intent.putExtra("cat_name", textview1);
                                                startActivity(intent);
                                            }
                                        }
                                    );
}

private void createDB()
{
    database = openOrCreateDatabase("AddictionCounter.db", SQLiteDatabase.CREATE_IF_NECESSARY, null);
    database.setLocale(Locale.getDefault());
    database.setVersion(1);

    try
    {
        String create_table_1 = "create table if not exists category (cat_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                                                                    " cat_server_id INTEGER," +
                                                                    " cat_name TEXT UNIQUE," +
                                                                    " parent_cat_id INTEGER," +
                                                                    " is_delete INTEGER," +
                                                                    " is_sync INTEGER," +
                                                                    " creation_date TEXT," +
                                                                    " update_date TEXT)";
        database.execSQL(create_table_1);

        String create_table_2 = "create table if not exists category_attribute (cat_attribute_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                                                                                " cat_attribute_server_id INTEGER," +
                                                                                " cat_server_id INTEGER," +
                                                                                " cat_id INTEGER," +
                                                                                " cat_attribute_name TEXT," +
                                                                                " cat_attribute_unit INTEGER," +
                                                                                " cat_limit INTEGER," +
                                                                                " is_delete INTEGER," +
                                                                                " is_sync INTEGER," +
                                                                                " creation_date TEXT," +
                                                                                " update_date TEXT)";
        database.execSQL(create_table_2);

        String create_table_3 = "create table if not exists category_limit (limit_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                                                                            " limit_server_id INTEGER," +
                                                                            " cat_id INTEGER," +
                                                                            " limit_count INTEGER," +
                                                                            " is_delete INTEGER," +
                                                                            " is_sync INTEGER," +
                                                                            " creation_date TEXT," +
                                                                            " update_date TEXT)";
        database.execSQL(create_table_3);

        String create_table_4 = "create table if not exists counter (counter_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                                                                    " counter_server_id INTEGER," +
                                                                    " cat_id INTEGER," +
                                                                    " cat_attribute_id INTEGER," +
                                                                    " cat_attribute_unit INTEGER," +
                                                                    " counter_entry_date TEXT," +
                                                                    " counter_entry_date_time TEXT," +
                                                                    " is_delete INTEGER," +
                                                                    " is_sync INTEGER)";
        database.execSQL(create_table_4);
    }
    catch(SQLException e)
    {
        Log.e("SQLException","The SQL string is invalid. ");
        Toast.makeText(getBaseContext(), "SQLException: The SQL string is invalid.", Toast.LENGTH_SHORT).show();
    }
    database.close();
}

private void loadDB() 
{
    database = openOrCreateDatabase("AddictionCounter.db", SQLiteDatabase.OPEN_READWRITE, null);
}

private void manageList()
{
    String addictionName="", todaysCount="", dailyLimit="", unit="";
    addictionList = new ArrayList<Addiction>();

    AddictionsData objAddictionsData = new AddictionsData();
    Cursor cursor = database.query("category", new String[]{"cat_id"}, null, null, null, null, null);
    if(cursor.getCount() > 0)
    {
        while(cursor.moveToNext())
        {
            int tmp_cat_id = cursor.getInt(0);

            addictionName = objAddictionsData.getAddictionName(tmp_cat_id);
            todaysCount = objAddictionsData.getTodaysCount(tmp_cat_id);
            dailyLimit = objAddictionsData.getDailyLimit(tmp_cat_id);
            unit = objAddictionsData.getUnit(tmp_cat_id);

            addictions = new Addiction[]{new Addiction(tmp_cat_id, addictionName, todaysCount, dailyLimit, unit)};
            addictionList.addAll( Arrays.asList(addictions) );
        }
        cursor.close();
    }
    listAdapter = new AddictionArrayAdapter(this, addictionList);
    database.close();//---------------------------
}

public int insertIntoCounter(int id)
{
    loadDB();//------------------------------------
    //---------------------insert the record-------------------

    ContentValues values = new ContentValues(); 
    int cat_attribute_id = 0;
    int cat_attribute_unit = 0;

    Cursor cursor1 = database.query("category_attribute", new String[]{"cat_attribute_id", "cat_attribute_unit"}, "cat_id=?", new String[]{id+""}, null, null, null);
    if(cursor1.getCount() > 0)
    {   
        while(cursor1.moveToNext())
        {
            cat_attribute_id = cursor1.getInt(0);
            cat_attribute_unit = cursor1.getInt(1);
        }
        cursor1.close();
    }

    Calendar c = Calendar.getInstance();
    SimpleDateFormat dtf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
    String currentTimeAndDate = dtf.format(c.getTime());
    SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
    String currentDate = df.format(c.getTime());

    values.put("counter_server_id", 0);
    values.put("cat_id", id);
    values.put("cat_attribute_id", cat_attribute_id);
    values.put("cat_attribute_unit", cat_attribute_unit);
    values.put("counter_entry_date", currentDate);
    values.put("counter_entry_date_time", currentTimeAndDate);
    values.put("is_delete", 0);
    values.put("is_sync", 0);

    try
    { 
        database.insert("counter", null, values);
    }
    catch(Exception e)
    {
        Log.e("Exception", e+"");
    }

    //------------------------LIMIT FUNCTIONSLITY---------------------

    //------------------------fetching attribute name

    cursor1 = database.query("category_attribute", new String[]{"cat_attribute_name"}, "cat_id=?", new String[]{id+""}, null, null, null);

    if(cursor1.getCount() > 0)
    {
        while(cursor1.moveToNext())
            attribute = cursor1.getString(0);
        cursor1.close();
    }

    //------------------------fetching limit

    cursor1 = database.query("category_limit", new String[]{"limit_count"}, "cat_id=?", new String[]{id+""}, null, null, null);
    if(cursor1.getCount() > 0)
    {
        while(cursor1.moveToNext())
            limit = cursor1.getInt(0);
        cursor1.close();
    }

    //--------------------------fetching todays count

    int todays_count = 0;

    Calendar cal1 = Calendar.getInstance();
    SimpleDateFormat dateFormat1 = new SimpleDateFormat("dd/MM/yyyy");
    String todays_date = dateFormat1.format(cal1.getTime());

    cursor1 = database.rawQuery("select sum(cat_attribute_unit) from counter where cat_id ="+id+" AND counter_entry_date = '"+todays_date+"';", null);

    while(cursor1.moveToNext())
        todays_count = cursor1.getInt(0);

    //---------------------sending acknowledgement

    int ack;

    if(todays_count < limit)
        ack = 0;
    else if(todays_count == limit)
        ack = 1;
    else
        ack = 2;

    return ack;
}

public static class Addiction
{
    private String cat_name = "", cat_todays_count="", cat_daily_limit="", cat_attribute_unit="";
    private int cat_id = 0;
    public Addiction(int id, String catName, String catTodaysCount, String catDailyLimit, String catAttributeUnit)
    {
        cat_id = id;
        cat_name = catName ;
        cat_todays_count = catTodaysCount;
        cat_daily_limit = catDailyLimit;
        cat_attribute_unit = catAttributeUnit;
    }
    public int getId()
    {
        return cat_id;
    }
    public String getCatName()
    {
        return cat_name;
    }
    public String getCatTodaysCount()
    {
        return cat_todays_count;
    }
    public String getCatDailyLimit()
    {
        return cat_daily_limit;
    }
    public String getCatAttributeUnit()
    {
        return cat_attribute_unit;
    }
}

private static class AddictionViewHolder
{
    private ImageView imageViewAddictionLog ;
    private TextView textViewAddictionName, textViewTodaysCount, textViewDailyLimit, textViewAttributeUnit ;

    public AddictionViewHolder( ImageView iv_log, TextView tv_addiction_name, TextView tv_todays_count, TextView tv_daily_limit, TextView tv_attribute_count)
    {
        imageViewAddictionLog = iv_log;
        textViewAddictionName = tv_addiction_name;
        textViewTodaysCount = tv_todays_count;
        textViewDailyLimit = tv_daily_limit;
        textViewAttributeUnit = tv_attribute_count;
    }
    public ImageView getImageViewAddLog()
    {
        return imageViewAddictionLog;
    }
    public TextView getTextViewAddictionName()
    {
        return textViewAddictionName;
    }
    public TextView getTextViewTodaysCount()
    {
        return textViewTodaysCount;
    } 
    public TextView getTextViewDailyLimit()
    {
        return textViewDailyLimit;
    } 
    public TextView getTextViewAttributeUnit()
    {
        return textViewAttributeUnit;
    } 
}

private static class AddictionArrayAdapter extends ArrayAdapter<Addiction>
{
    private LayoutInflater inflater;
    StartActivity objStartActivity = new StartActivity();

    public AddictionArrayAdapter( Context context, List<Addiction> addictionList )
    {
        super( context, R.layout.single_row_start, R.id.textViewStartAddictionName, addictionList );
        inflater = LayoutInflater.from(context);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        Addiction addiction = (Addiction) this.getItem( position );

        ImageView imageViewAddLog ; 
        TextView textViewAN ;
        final TextView textViewTC;
        final TextView textViewDL;
        final TextView textViewU;

        if(convertView == null)
        { 
            convertView = inflater.inflate(R.layout.single_row_start, null);

            imageViewAddLog = (ImageView) convertView.findViewById(R.id.imageViewStartAdd);
            textViewAN = (TextView) convertView.findViewById(R.id.textViewStartAddictionName);
            textViewTC = (TextView) convertView.findViewById(R.id.textViewStartTodaysCountValue);
            textViewDL = (TextView) convertView.findViewById(R.id.textViewStartDailyLimitCount);
            textViewU = (TextView) convertView.findViewById(R.id.textViewStartAddictionUnit);

            imageViewAddLog.setFocusable(false);
            imageViewAddLog.setFocusableInTouchMode(false);
            imageViewAddLog.setClickable(true);

            convertView.setTag( new AddictionViewHolder(imageViewAddLog, textViewAN, textViewTC, textViewDL, textViewU) );

            imageViewAddLog.setOnClickListener( new View.OnClickListener()
                                                {
                                                    public void onClick(View v)
                                                    {
                                                        ImageView ib = (ImageView) v ;
                                                        Addiction addiction = (Addiction) ib.getTag();

                                                        int tmp_cat_id = addiction.getId();

                                                        int ack = objStartActivity.insertIntoCounter(tmp_cat_id);

                                                        String cat_name = addiction.getCatName();
                                                        switch(ack)
                                                        {
                                                            case 0:
                                                                String message0 = "Record added Successfully.";
                                                                customShowDialog(message0, tmp_cat_id);
                                                                break;

                                                            case 1:
                                                                String message1 = "Please stop "+cat_name+". Today you have already added "+limit+" "+ attribute+". Your daily limit is "+limit+" "+attribute+".";
                                                                customShowDialog(message1, tmp_cat_id);
                                                                break;

                                                            case 2:
                                                                String message2 = "Please stop "+cat_name+". Today you have already added "+limit+" "+ attribute+". You have crossed your daily limit of "+limit+" "+attribute+".";
                                                                customShowDialog(message2, tmp_cat_id);
                                                                break;
                                                        }
                                                    }

                                                    private void customShowDialog(String message, final int cat_id)
                                                    {
                                                        AlertDialog.Builder adb = new Builder(getContext());
                                                        adb.setTitle("Success !!!");
                                                        adb.setMessage(message);
                                                        adb.setIcon(R.drawable.ic_launcher);
                                                        adb.setPositiveButton("Ok",new DialogInterface.OnClickListener()
                                                                                    {
                                                                                        public void onClick(DialogInterface arg0, int arg1)
                                                                                        {
                                                                                            arg0.cancel();
                                                                                            AddictionsData ad = new AddictionsData();
                                                                                            textViewTC.setText( ad.getTodaysCount(cat_id));
                                                                                            textViewDL.setText( ad.getDailyLimit(cat_id));
                                                                                            textViewU.setText( ad.getUnit(cat_id));
                                                                                        }
                                                                                    }
                                                                            );

                                                        AlertDialog ad = adb.create();
                                                        ad.show();
                                                    }
                                                }
                                            );
        }

        else
        {
            AddictionViewHolder viewHolder = (AddictionViewHolder) convertView.getTag();    
            imageViewAddLog = viewHolder.getImageViewAddLog();

            textViewAN = viewHolder.getTextViewAddictionName();


            textViewTC = viewHolder.getTextViewTodaysCount();


            textViewDL = viewHolder.getTextViewDailyLimit();


            textViewU = viewHolder.getTextViewAttributeUnit();

        }

        imageViewAddLog.setTag( addiction );
        textViewAN.setText( addiction.getCatName());
        textViewTC.setText( addiction.getCatTodaysCount());
        textViewDL.setText( addiction.getCatDailyLimit());
        textViewU.setText( addiction.getCatAttributeUnit());

        return convertView;
    }  
}

public static class AddictionsData
{
    Cursor cursor;

    String getAddictionName(int cat_id)
    {
        String tmp_name = null;
        cursor = database.query("category", new String[]{"cat_name"}, "cat_id=?", new String[]{cat_id+""}, null, null, null);
        if(cursor.getCount() > 0)
        {
            while(cursor.moveToNext())
            {
                tmp_name = cursor.getString(0);
            }
            cursor.close();
        }
        return tmp_name;
    }
    String getTodaysCount(int cat_id)
    {
        String todaysCount = null;

        int todays_count = 0;

        Calendar cal1 = Calendar.getInstance();
        SimpleDateFormat dateFormat1 = new SimpleDateFormat("dd/MM/yyyy");
        String todays_date = dateFormat1.format(cal1.getTime());

        cursor = database.rawQuery("select sum(cat_attribute_unit) from counter where cat_id ="+cat_id+" AND counter_entry_date = '"+todays_date+"';", null);
        if(cursor.getCount() > 0)
        {
            while(cursor.moveToNext())
            {
                todays_count = cursor.getInt(0);
            }
            cursor.close();
        }

        String attribute = null;
        cursor = database.query("category_attribute", new String[]{"cat_attribute_name"}, "cat_id=?", new String[]{cat_id+""}, null, null, null);
        if(cursor.getCount() > 0)
        {
            while(cursor.moveToNext())
            {
                attribute = cursor.getString(0);
            }
            cursor.close();
        }

        todaysCount = todays_count+" "+attribute;
        return todaysCount;
    }

    String getDailyLimit(int cat_id)
    {
        String dailyLimit;

        int daily_limit = 0;
        cursor = database.query("category_limit", new String[]{"limit_count"}, "cat_id=?", new String[]{cat_id+""}, null, null, null);
        if(cursor.getCount() > 0)
        {
            while(cursor.moveToNext())
                daily_limit = cursor.getInt(0);
            cursor.close();
        }

        String attribute = null;
        cursor = database.query("category_attribute", new String[]{"cat_attribute_name"}, "cat_id=?", new String[]{cat_id+""}, null, null, null);
        if(cursor.getCount() > 0)
        {
            while(cursor.moveToNext())
            {
                attribute = cursor.getString(0);
            }
            cursor.close();
        }
        dailyLimit = daily_limit+ " "+attribute;
        return dailyLimit;
    }

    String getUnit(int cat_id)
    {
        String unit;

        int _unit = 0;
        cursor = database.query("category_attribute", new String[]{"cat_attribute_unit"}, "cat_id=?", new String[]{cat_id+""}, null, null, null);
        if(cursor.getCount() > 0)
        {
            while(cursor.moveToNext())
                _unit = cursor.getInt(0);
            cursor.close();
        }

        String attribute = null;
        cursor = database.query("category_attribute", new String[]{"cat_attribute_name"}, "cat_id=?", new String[]{cat_id+""}, null, null, null);
        if(cursor.getCount() > 0)
        {
            while(cursor.moveToNext())
            {
                attribute = cursor.getString(0);
            }
            cursor.close();
        }
        unit = _unit+ " "+attribute;
        return unit;
    }
}
}

我的主要布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/main_bg_edited" >

    <ImageView
        android:id="@+id/imageViewStart"
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:src="@drawable/setting_icon"
        android:layout_marginRight="7dp" />

    <ListView
        android:id="@+id/listViewStart"
        android:layout_width="290dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/imageViewStart"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        android:divider="@android:color/transparent"
        android:dividerHeight="10dp"
        android:drawSelectorOnTop="true" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/imageViewStart"
        android:layout_centerHorizontal="true"
        android:text="Addictions"
        style="@style/header_style" />

</RelativeLayout>

我正在给视图充气的布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/box_midbg" >

    <TextView
        android:id="@+id/textViewStartTodaysCountValue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textViewStartAddictionName"
        android:layout_toRightOf="@+id/textViewTodaysCount"
        android:text=" TextView"
        android:textSize="10sp"
        android:textColor="#ffffff" />

    <TextView
        android:id="@+id/textViewStartDailyLimitCount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/textViewStartTodaysCountValue"
        android:layout_alignTop="@+id/textViewDailyLimit"
        android:text="TextView"
        android:textSize="10sp"
        android:textColor="#ffffff" />

    <TextView
        android:id="@+id/textViewStartAddictionUnit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/textViewStartTodaysCountValue"
        android:layout_marginRight="15dp"
        android:text="TextView"
        android:textColor="#ffffff"
        android:textSize="10sp" />

    <TextView
        android:id="@+id/textViewStartAddictionName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/imageViewStartAdd"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="15dp"
        android:text="TextView"
        android:textColor="#ffffff"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/textViewTodaysCount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/textViewStartAddictionUnit"
        android:layout_alignLeft="@+id/textViewStartAddictionName"
        android:text="Today&apos;s Counts : "
        android:textColor="#ffffff"
        android:textSize="10sp" />

    <TextView
        android:id="@+id/textViewDailyLimit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textViewTodaysCount"
        android:layout_below="@+id/textViewTodaysCount"
        android:text="Daily Limit :"
        android:textColor="#ffffff"
        android:textSize="10sp" />

    <ImageView
        android:id="@+id/imageViewStartAdd"
        android:layout_width="25sp"
        android:layout_height="25sp"
        android:layout_alignRight="@+id/textViewStartAddictionUnit"
        android:layout_centerVertical="true"
        android:clickable="true"
        android:src="@drawable/add_btn" />

</RelativeLayout>

2 个答案:

答案 0 :(得分:1)

您不应该将数据存储在视图中,因为视图会被回收,而且几乎可以肯定会发生什么。以下

Addiction addiction = (Addiction) ib.getTag();
....
imageViewAddLog.setTag( addiction );

不可取。更好的方法是让列表视图处理点击,以便您可以知道单击了哪个视图以及与视图位置对应的正确Addiction对象。

myList.setOnItemClickListener(
    new OnItemClickListener()
    {
        @Override
        public void onItemClick(AdapterView<?> arg0, View view,
                int position, long id) {
               Addiction addiction = (Addiction) myList.getItemAtPosition(position);
               ...rest of code...

             }
        }
 );

答案 1 :(得分:0)

请将所有其他代码放在

之后
convertView.setTag( new AddictionViewHolder(imageViewAddLog, textViewAN, textViewTC, textViewDL, textViewU) );

if之外,尝试从代码中删除else

else之后,if的其余代码将相同。请注意,当convertview为空时,请创建一个新的holder并设置为Tag。然后在Tag不为空时从convertview检索该对象。并在

之后编写所有其他代码,例如将值设置为视图等
AddictionViewHolder viewHolder = (AddictionViewHolder) convertView.getTag();