Search code examples
androidlistviewarraylistcustom-adapter

Android Studio ListView Custom adapter no data displayed


I'm trying to list rows with columns from an ArrayList that is populated with Shop types, as extracted from an SQLite database. As such I have a Custom Adapter.

However, no data gets displayed. There are no error messages or exceptions.

I've used the debugger (I'm using Android Studio). I know that that overridden getView method isn't being invoked (Breakpoints in this method weren't triggered). A breakpoint in the constructor was triggered and the expected data was in the ArrayList.

The ListView, has worked for other methods (I've progressed from a simple list with data in a string array which confirms, amongst other tests for data existing, such as a dialog display the data, to a simple list using an ArrayList of Shop type, which list the elements rather than the data).

There could perhaps be issues with the rowview XML.

I would greatly appreciate someone letting me know what is wrong with the code (as below) in regards to the above issue. ie Why nothing is being displayed and also how to correct the code, if time permits.

I'd just like to confirm that I looked at many posts in regards to this and tried various options, some you can see in the code.

This is an extract of the MainShopActivity that I think is relevant (complete code is last as it's ugly and has a lot of code commented out).

    ShopListArrayAdapter adapter = new ShopListArrayAdapter(this,shoplist);
    //listview.setAdapter(adapter);
    setListAdapter(adapter);

Here's ShopListArrayAdapter.

package mjt.shopper;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;

/**
 * Created by Mike092015 on 1/02/2016.
 */
public class ShopListArrayAdapter extends ArrayAdapter<ArrayList<Shop>> {
    private final Context context;
    private final ArrayList<Shop> shoplist;

    public ShopListArrayAdapter(Context context, ArrayList<Shop> shoplist) {
         super(context, R.layout.activity_shop_list_entry);
        this.context = context;
        this.shoplist = shoplist;
     }

    @Override
    public View getView(int position, View convertview, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView = inflater.inflate(R.layout.activity_shop_list_entry, parent, false);

        TextView textViewShopName = (TextView) rowView.findViewById(R.id.shop_name_entry);
        TextView textViewShopOrder = (TextView) rowView.findViewById(R.id.shop_order_entry);
        TextView textviewShopStreet = (TextView) rowView.findViewById(R.id.shop_street_entry);

        textViewShopName.setText(shoplist.get(position).getShopName());
         textViewShopOrder.setText(shoplist.get(position).getShopOrderAsString());
        textviewShopStreet.setText(shoplist.get(position).getShopstreet());
        return rowView;
    }
}

Here's the ListeView XML activity_shop_list (ps I tried with the four buttons removed, the results were the same.).

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="mjt.shopper.ShopListActivity">

<Button
    android:id="@+id/aslhbtn01"
    android:layout_width="@dimen/standard_button_width"
    android:layout_height="@dimen/standard_button_height"
    android:text="@string/standarddonebutton"
    android:textStyle="bold"
    android:onClick="doneWithShops"/>
<Button
    android:id="@+id/aslhbtn02"
    android:layout_width="@dimen/standard_button_width"
    android:layout_height="@dimen/standard_button_height"
    android:layout_toEndOf="@id/aslhbtn01"
    android:layout_toRightOf="@id/aslhbtn01"
    android:text="@string/standardaddbuttontext"
    android:textStyle="bold"
    android:onClick="addShop"
    />

<ListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/aslhbtn01"/>

<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@android:id/list">

    <Button
        android:id="@+id/aslfbtn01"
        android:layout_width="@dimen/standard_button_width"
        android:layout_height="@dimen/standard_button_height"
        android:text="@string/standarddonebutton"
        android:textStyle="bold"
        android:onClick="doneWithShops"/>
    <Button
        android:id="@+id/aslfbtn02"
        android:layout_width="@dimen/standard_button_width"
        android:layout_height="@dimen/standard_button_height"
        android:layout_toEndOf="@id/aslfbtn01"
        android:layout_toRightOf="@id/aslfbtn01"
        android:text="@string/standardaddbuttontext"
        android:textStyle="bold"
        android:onClick="addShop"/>

</RelativeLayout>

Here's the RowView XML activity_shop_list_entry

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".ShopListEntryActivity">
<TextView
    android:id="@+id/shop_name_entry"
    android:layout_width="100sp"
    android:layout_height="30sp"
    android:textStyle="bold" />
<TextView
    android:id="@+id/shop_order_entry"
    android:layout_width="50sp"
    android:layout_height="30sp" />
<TextView
    android:id="@+id/shop_street_entry"
    android:layout_width="300sp"
    android:layout_height="30sp" />
</LinearLayout>

Finally the complete code for ShopListActivity

    package mjt.shopper;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import java.util.ArrayList;

public class ShopListActivity extends ListActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shop_list);
    int shopcount = 0;


    // Need to access the shopper database
    ShopperDBHelper shopperdb = new ShopperDBHelper(this, null, null,1);

    // Check to see if we should have action buttons at top and bottom of the list
    // if so then make the upper buttons invisible. Just in case if not then make
    // them visible.
    shopcount = shopperdb.numberOfShops();
    if(shopcount < 10) {
        findViewById(R.id.aslhbtn01).setVisibility(View.INVISIBLE);
        findViewById(R.id.aslhbtn02).setVisibility(View.INVISIBLE);
    } else {
        findViewById(R.id.aslhbtn01).setVisibility(View.VISIBLE);
        findViewById(R.id.aslhbtn02).setVisibility(View.VISIBLE);
    }

    // Call the getShops method setting an ArrayList with the returned ArrayList (list of Shop objects)
    final ArrayList<Shop> shoplist = shopperdb.getShops();

    //Testing ie display number of shops via both the numberOfShops method and via the ArrayList size method
    //     according to the ArrayList returned from the getShops method.
    //          numberOfShops method returns integer count
    //          getShops method returns an ArrayList of the Shop object per row, this containing all the data
    String r;   // initialise the string that is to be displayed

    // Testing Add the number of shops extracted (both count methods as described above)
    r = "Shop List Array contains " + shoplist.size() + " Elements.\nNumber of Shops returns "+shopcount+"\n";

    // Alternative/check simplelistview compliant array
    final String[] values = new String[shoplist.size()];
    int ix = 0;

    // Testing report on the contents of the returned list of Shops, also populate the simplelistview array
    for(Shop shop : shoplist) {
        values[ix++] = shop.getShopName();
        r=r+"Shop Name="+shop.getShopName()+
                " Order="+shop.getShopOrderAsString()+
                " Street="+shop.getShopstreet()+
                " City="+shop.getShopCity()+
                " State="+shop.getShopstate()+
                " Notes="+shop.getShopNotes()+
                " DBID="+shop.getShopId()+
                "\n\n";
    }
    // Testing report shop list according to the simplelistview array
    r = r+"\n\nExtract Shop names are:";
    for(int i=0;i < shoplist.size(); i++ ) {
        r=r+"\n     "+values[i];
    }

    // Build the simplelistview (ie just one column, the shop name)
    /*WORKS but now trying arraylist adapter
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,values);
    final ListView listview = (ListView) findViewById(R.id.aslv01);
    // Set up the onclick listener per list item
    listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Toast.makeText(getApplicationContext(),"You Clicked on List Item #"+position+" Shop="+values[position]+". ALtMthd Shop="+shoplist.get(position).getShopName(),Toast.LENGTH_LONG).show();
        }
    });
    listview.setAdapter(adapter);
    */


    ShopListArrayAdapter adapter = new ShopListArrayAdapter(this,shoplist);
    //listview.setAdapter(adapter);
    setListAdapter(adapter);

    // sort of works shows the id of the shoplist element but for all shops
    //ArrayAdapter<Shop> adadpter = new ArrayAdapter<Shop>(this,android.R.layout.simple_list_item_1,shoplist);
    //listview.setAdapter(adapter);


    AlertDialog.Builder okdialog = new AlertDialog.Builder(this);
    okdialog.setMessage(r);
    okdialog.setCancelable(true);
    okdialog.setPositiveButton("OK",new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.cancel();
        }
    });
    okdialog.show();

}


public void doneWithShops(View view) { this.finish(); }
public void addShop(View view) {
    ShopperDBHelper shopperdb = new ShopperDBHelper(this, null, null, 1);
    final ArrayList<Shop> shoplist = shopperdb.getShops();

    Intent intent = new Intent(this,ShopAddActivity.class);
    startActivity(intent);
    final String[] values = new String[shoplist.size()];
    int ix = 0;
    for(Shop shop : shoplist) {
        values[ix++] = shop.getShopName();
    }
    //ArrayAdapter<String> adapter = new ArrayAdapter<String>(view.getContext(), android.R.layout.simple_list_item_1,values);
    //@@@@@@@@ final ListView listview = (ListView) findViewById(R.id.aslv01);
    //final ListView listview = (ListView) findViewById(R.id.aslv01);
}

}


Solution

  • you are not submitting the dataset to the parent class. Change

    public ShopListArrayAdapter(Context context, ArrayList<Shop> shoplist) {
          super(context, R.layout.activity_shop_list_entry);
    

    with

    public ShopListArrayAdapter(Context context, ArrayList<Shop> shoplist) {
     super(context, R.layout.activity_shop_list_entry, shoplist);
    

    of course shoplist must contains entries, otherwise nothing is shown anyway. After you call setAdapter Android calls ArrayAdapter.getCount, to check whether or nor getView needs to be called. Since you are neither providing explicitly the dataset to the parent class nor overriding getCount, from the Android POV you don't have anything to show, ergo getView is not called.

    Edit

    Change

    public class ShopListArrayAdapter extends ArrayAdapter<ArrayList<Shop>> {
    

    with

    public class ShopListArrayAdapter extends ArrayAdapter<Shop> {