• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

ListView not displaying custom arrayList adapter

Hello, I have been struggling with this for some time now. I am trying to populate a ListView from an arrayList, but my ListView isn't populating. I have gone through every relevant thread I have found on the internet and I still can't figure out why this isn't working. Also I checked to make sure the arrayList was populated and it is.
I have no errors, but the ListView just displays blank. If anyone can figure out why it isn't working I will mail you a cookie! Debugging this is just getting depressing. Thanks!!!
Adapter:
Code:
public class ResultAdapter extends ArrayAdapter<User> implements View.OnClickListener {  //implements View.OnClickListener
    // private Activity activity;

    Context mContext;
    //private static LayoutInflater inflater = null;
    private int layoutResourceId;
    private static final String LOG_TAG = "ResultAdapter";
    private ArrayList<User> users;

    private class ViewHolder {  //static
        TextView usrName;
        TextView usrSchool;
        TextView usrEmail;
    }

    //public ResultAdapter(Context context, ArrayList<User> users)
    public ResultAdapter(ArrayList<User> data, Context context) {
        super(context, R.layout.list_item, data);
        this.users = data;
        this.mContext = context;

    }

    @Override
    public void onClick(View v) {
        int position = (Integer) v.getTag();
        Object object = getItem(position);
        User user=(User)object;
        
    }
    private int lastPosition = -1;

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        User user = getItem(position);
        ViewHolder viewHolder;
        final View result;


        if (convertView == null) {
            viewHolder = new ViewHolder();
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.list_item, parent, false); //activity_usermatch
            viewHolder.usrName = (TextView) convertView.findViewById(R.id.resultName);
            viewHolder.usrEmail = (TextView) convertView.findViewById(R.id.resultEmail);
            viewHolder.usrSchool = (TextView) convertView.findViewById(R.id.resultSchool);
            result = convertView;

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
            result = convertView;
        }
        Animation animation = AnimationUtils.loadAnimation(mContext, (position > lastPosition) ? R.anim.up_from_bottom : R.anim.down_from_top);
        result.startAnimation(animation);
        lastPosition = position;
        viewHolder.usrName.setText(user.getName());
        viewHolder.usrEmail.setText(user.getEmail());
        viewHolder.usrSchool.setText(user.getSchool());


        return result; //convertView
    }
}
Main Activity for the function:
Code:
public class UserMatchActivity extends AppCompatActivity{
    private static final String TAG = UserMatchActivity.class.getSimpleName();
    private ProgressDialog pDialog;
    private SessionManager session;
    private SQLiteHandler db;
    public ArrayList<User> matchList;
    ListView listView;
    private static ResultAdapter adapter;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        matchList = new ArrayList<>();
        setContentView(R.layout.activity_match_main); //activity_match_main  activity_usermatch
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

        // Progress dialog
        pDialog = new ProgressDialog(this);
        pDialog.setCancelable(false);

        // Session manager
        session = new SessionManager(getApplicationContext());

        // SQLite database handler
        db = new SQLiteHandler(getApplicationContext());
        HashMap<String, String> user = db.getUserDetails();
        String name = user.get("name");
        String email = user.get("email");
        final String school = user.get("school");

        //get name,email,school of all matches who go to the same school

        String tag_string_req = "get_matches";
        StringRequest strReq = new StringRequest(Request.Method.POST,
                AppConfig.URL_SEARCH, new Response.Listener<String>() { //{
            @Override
            public void onResponse(String response) {  //JSONObject response
                hideDialog();

                try {
                    JSONArray jObj = new JSONArray(response);
                    boolean error = false;
                    String errortest = String.valueOf(error);
                    Log.d("error", errortest);
                    error = false;

                    if (!error) {
                        for (int i = 0; i < jObj.length(); i++) {
                            JSONObject childJSONObject = jObj.getJSONObject(i);
                            String name = childJSONObject.getString("name");
                            //Log.d("name", String.valueOf(name));
                            String email = childJSONObject.getString("email");
                            //Log.d("email", String.valueOf(email));
                            String sch = childJSONObject.getString("school");
                            //Log.d("school", String.valueOf(sch));
                            User usr = new User(name, email, sch);
                            matchList.add(usr);

                        }
                        //Testing to verify matchList my arrayList isn't empty, and it isn't
                        String koala = Integer.toString(matchList.size());
                        Log.d("testing123", koala);

                    } else {
                        String errorMsg = ("brokelol");
                        Toast.makeText(getApplicationContext(),
                                errorMsg, Toast.LENGTH_LONG).show();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show();
                }

            }

        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Match Error: " + error.getMessage());
                Toast.makeText(getApplicationContext(),
                        error.getMessage(), Toast.LENGTH_LONG).show();
                hideDialog();
            }
        }) {

            @Override
            protected Map<String, String> getParams() {
                // Posting parameters to search url
                Map<String, String> params = new HashMap<>();
                params.put("school", school);
                return params;
            }

        };
        AppController.getInstance().addToRequestQueue(strReq, tag_string_req);

        adapter = new ResultAdapter(matchList, getApplicationContext());
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
            @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id){
                User users = matchList.get(position);
                Snackbar.make(view, "Name: "+users.getName()+"\n"+"School: "+users.getSchool()+"\n"+"Email: "+users.getEmail(), Snackbar.LENGTH_LONG)
                        .setAction("No action", null).show();
            }
        });

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void hideDialog() {
        if (pDialog.isShowing())
            pDialog.dismiss();
    }
}

Here is my XML code.
menu_main.xml:
Code:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context=".UserMatchActivity">
    <item android:id="@+id/action_settings"
        android:title="action_settings"
        android:orderInCategory="100"  />
    <ListView
        android:id="@+id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</menu>

activity_usermatch.xml:
Code:
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/listMatches">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="vertical"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:id="@+id/MatchLayout">
        <ProgressBar
            android:id="@+id/progressBar"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>


    </LinearLayout>
</ListView>

list_item.xml:
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/resultName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Name"
        />
    <TextView
        android:id="@+id/resultEmail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Email"
        />
    <TextView
        android:id="@+id/resultSchool"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="School"
        />

</LinearLayout>

And here is the User class:
Code:
public class User {
    public String usrname;
    public String usremail;
    public String usrschool;

    public User(JSONObject object) {
        try {
            this.usrname = object.getString("name");
            this.usremail = object.getString("email");
            this.usrschool = object.getString("school");
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    public User(String name, String email, final String school){
        this.usrname = name;
        this.usremail = email;
        this.usrschool = school;
    }

    /*public User(String name, String email, String school) {
        this.usrname = name;
        this.usremail = email;
        this.usrschool = school;}*/

    public void setUsrname(final String name) {
        usrname = name;
    }

    public void setUsremail(final String email) {
        usremail = email;
    }

    public void setUsrschool(final String school) {
        usrschool = school;
    }

    public String getName() {
        return usrname;
    }

    public String getEmail() {
        return usremail;
    }

    public String getSchool() {
        return usrschool;
    }


}

Any input would be highly appreciated! Like I said, I have been struggling with this for quite some time now and it is driving me crazy! Also, I am not trying to be a mooch. I will gladly help out other members on the forum once I get this figured out and get my sanity back, as this seems like a great place. Please and thanks!
 
Last edited:
Simply put, you're creating your ListAdapter before the matchList array has been populated.
This line constructs your ListAdapter -

Code:
adapter = new ResultAdapter(matchList, getApplicationContext());

I would put money on the fact that the ResultAdapter constructor is called when matchList has nothing in it.
Why is this?
Well the point at which you populate the list is done in the response method for your HTTP request. The request is made asynchronously, so any code after you initiated the request is executed immediately, without waiting for the response.

To confirm this, put a breakpoint in the ResultAdapter constructor method, and check the contents of the matchList parameter.

What to do? Well in your onResponse() method, after populating matchList, you should tell the ListAdapter that the underlying data has changed. Do this by calling

Code:
adapter.notifyDataSetChanged()
 
When I put breakpoints it said that data was size 0, this.mContext = null and this.users = null. I added adapter.notifyDataSetChanged(); after I constructed the adapter in my OnRespones() method, but it still isn't displaying. I'm going to use FindBugs to see if I can find a static cause for my issues.
 
Here's a suggestion: Create your ListAdapter with some hardcoded test data. If it doesn't work with this setup, you're doing something fundamentally wrong.
 
I hardcoded some data into my ArrayList and it displays! So now I just have to play around with the code that populates the ArrayList from database data.
 
Last edited:
I got it working! I added:
Code:
adapter.notifyDataSetChanged();
at the bottom of the loop where I populate the ArrayList! Thank you so much for all of your help LV426!!!!!
 
Back
Top Bottom