Custom listview with empty arraylist

Listview with image and two textviews. It crashes the first time i enter if theres no object to print or to show. It cant get a blank listview if the arraylist is empty.

public contactoAdapter(Context context, ArrayList<contactoAgenda> datos) {
                super(context, R.layout.listview_item, datos);
                // Guardamos los par�metros en variables de clase.
                this.context = context;
                this.datos = datos;
            }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            View item = convertView; 
            contactoHolder holder;

            if (item == null) {
                item = LayoutInflater.from(context).inflate(R.layout.listview_item,
                        null);

                holder = new contactoHolder();
                holder.imgContacto = (ImageView) item.findViewById(R.id.imagenContacto);
                holder.tvMail = (TextView) item.findViewById(R.id.tvMail);
                holder.tvNombre = (TextView) item.findViewById(R.id.tvNombre);

                // Almacenamos el holder en el Tag de la vista.
                item.setTag(holder);
            }

            holder = (contactoHolder) item.getTag();

           holder.imgContacto.setImageResource(datos.get(position).getDrawableImageID());

            holder.tvNombre.setText(datos.get(position).getNombre());
            holder.tvMail.setText(datos.get(position).getDireccion());


            return item;
        }

I fill the arraylist with all the contacts in one table. So the first time the table is empty till you fill in with some contacts.

public ArrayList<contactoAgenda> recuperarTodosContactos() {
        SQLiteDatabase db = getReadableDatabase();
        ArrayList<contactoAgenda> lista_contactos = new ArrayList<contactoAgenda>();
        String[] valores_recuperar = {"nombre","direccion","telefono","email","miembrofacebook","miembrotwitter","miembrogoogle","miembrolinkedin","sexo","tipocontacto","imagen"};
        Cursor c = db.query("contactos", valores_recuperar, null, null, null, null, null, null);
        c.moveToFirst();
        do {
            contactoAgenda contactos = new contactoAgenda(c.getString(0), c.getString(1), c.getString(2), c.getString(3),c.getInt(4), c.getInt(5), c.getInt(6), c.getInt(7),c.getInt(8), c.getString(9), c.getInt(10));
            lista_contactos.add(contactos);
        } while (c.moveToNext());


        db.close();
        c.close();
        return lista_contactos;
    }

I call it like using global variables, the important thing i get an arraylist of contacts to display in thee adapter. Every case works fine except the particular one. The first time the arraylist is empty. Ive tried a listview with contacts and delete them and i can get the listview in blank... Dont know the reason. If the arraylist is empty, it had to show a blank listview:

AgendaGlobal.getInstance().miAgenda = BaseDatosGlobal.getInstance(this).agendaBaseDatos.recuperarTodosContactos();

                Toast.makeText(getApplicationContext(),"Hasta aqui ya no", Toast.LENGTH_LONG).show();

                adapter = new contactoAdapter(this, AgendaGlobal.getInstance().miAgenda);

                lvContactos = (ListView) findViewById(R.id.lvItems);
                // Asignamos el Adapter al ListView, en este punto hacemos que el
                // ListView muestre los datos que queremos.


                lvContactos.setAdapter(adapter);

The logcat:Notice that before i had an arraylist in a global variable and the same happenned...if i get an arraylist with empty data it crashes. Not is database only related.

01-29 18:53:43.425: E/AndroidRuntime(1712): FATAL EXCEPTION: main
01-29 18:53:43.425: E/AndroidRuntime(1712): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.informacion/com.example.informacion.MainActivity}: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.app.ActivityThread.access$600(ActivityThread.java:123)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.os.Looper.loop(Looper.java:137)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.app.ActivityThread.main(ActivityThread.java:4424)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at java.lang.reflect.Method.invokeNative(Native Method)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at java.lang.reflect.Method.invoke(Method.java:511)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at dalvik.system.NativeStart.main(Native Method)
01-29 18:53:43.425: E/AndroidRuntime(1712): Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.database.AbstractCursor.checkPosition(AbstractCursor.java:400)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at com.example.informacion.BaseDatosContactos.recuperarTodosContactos(BaseDatosContactos.java:295)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at com.example.informacion.MainActivity.onCreate(MainActivity.java:68)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.app.Activity.performCreate(Activity.java:4465)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
01-29 18:53:43.425: E/AndroidRuntime(1712):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
01-29 18:53:43.425: E/AndroidRuntime(1712):     ... 11 more

Upvotes: 0

Views: 1356

Answers (2)

labreu
labreu

Reputation: 444

Don't know for sure what the problem is, that code you put there does't show the problem, but some things that could make some difference:

  1. Extend your adapter from BaseAdapter, you don't need to call super() in your constructor.
  2. You should override the getCount(), getItem(int position) and getItemId(int position) in your adapter. This is important, the method getCount() says to the getView() how many times it will be called, if you list is empty the getView() will never get called. In your case should be something like:

    @Override
    public int getCount() {
        return datos.size();
    }
    
    @Override
    public String getItem(int position) {
        return datos.get(position);
    }
    
    @Override
    public long getItemId(int position) {
        return position;
    }
    
  3. This has nothing to do with your problem but is a good practice: use directly the View convertView instead of creating a new View item, it's fine like that but you are using memory for instantiate a new item that you don't need.

  4. This is an advice most than anything: when you load a cursor from database ask for the getCount() > 0 before make the loop. Something like this:

    Cursor c = db.query("contactos", valores_recuperar, null, null, null, null, null, null);
    
    if (c.getCount() > 0) {
        c.moveToFirst();
        while (cursor.moveToNext()) {
            contactoAgenda contactos = new contactoAgenda(c.getString(0), c.getString(1), c.getString(2), c.getString(3),c.getInt(4), c.getInt(5), c.getInt(6), c.getInt(7),c.getInt(8), c.getString(9), c.getInt(10));
            lista_contactos.add(contactos);
        }
    }
    c.close();
    

Don't know if this would help you but take a look at. If you post more info (logcat, more code) we can find the problem exactly. Hope it helps

EDIT:

Ok by the logcat you paste the error is in this line: com.example.informacion.BaseDatosContactos.recuperarTodosContactos(BaseDatosContactos.java:295)

and is a CursorOutOfBounds error, the point 4 of this answer should fix that error. The problem is that you are trying to make a loop and you are asking for items to a cursor that is empty, that's why I told you that when you will loop over a cursor ask for the count to be higher than 0, so for that problem you put in there the solution is replace you code in recuperarContactos for this one:

    Cursor c = db.query("contactos", valores_recuperar, null, null, null, null, null, null);

    if (c.getCount() > 0) {
        c.moveToFirst();
        while (cursor.moveToNext()) {
            contactoAgenda contactos = new contactoAgenda(c.getString(0), c.getString(1), c.getString(2), c.getString(3),c.getInt(4), c.getInt(5), c.getInt(6), c.getInt(7),c.getInt(8), c.getString(9), c.getInt(10));
            lista_contactos.add(contactos);
        }
    }
    c.close();

Upvotes: 1

Example: in rellenarArrayList i had to put some contacts in miAgenda which is an ArrayList of contactoAgenda. If the arraylist is empty the adapter crashes. So your note is useful in sqlite cases, but is not the problem here..i guess

rellenarArrayList();


                adapter = new contactoAdapter(this, AgendaGlobal.getInstance().miAgenda);

                lvContactos = (ListView) findViewById(R.id.lvItems);
                // Asignamos el Adapter al ListView, en este punto hacemos que el
                // ListView muestre los datos que queremos.


                lvContactos.setAdapter(adapter);
                // Asignamos el Listener al ListView para cuando pulsamos sobre uno de
                // sus items.

Just in case here again the adapter for a custom listview.

public contactoAdapter(Context context, ArrayList<contactoAgenda> datos) {
                super(context, R.layout.listview_item, datos);
                // Guardamos los par�metros en variables de clase.
                this.context = context;
                this.datos = datos;
            }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            View item = convertView; 
            contactoHolder holder;

            if (item == null) {
                item = LayoutInflater.from(context).inflate(R.layout.listview_item,
                        null);

                holder = new contactoHolder();
                holder.imgContacto = (ImageView) item.findViewById(R.id.imagenContacto);
                holder.tvMail = (TextView) item.findViewById(R.id.tvMail);
                holder.tvNombre = (TextView) item.findViewById(R.id.tvNombre);

                // Almacenamos el holder en el Tag de la vista.
                item.setTag(holder);
            }

            holder = (contactoHolder) item.getTag();

           holder.imgContacto.setImageResource(datos.get(position).getDrawableImageID());

            holder.tvNombre.setText(datos.get(position).getNombre());
            holder.tvMail.setText(datos.get(position).getDireccion());


            return item;
        }

Upvotes: 0

Related Questions