1

I am working on application that needs to get data from online MySQL database and show it as list in activity layout.

Problem is that my application gets error " Attempt to invoke interface method 'int java.util.List.size()' on a null object reference"

In onCreate method I am calling asyncTask class to get the data from server and than below that line of code I set that data through adapter to listview which is my layout. When starting that activity, I get the error.

Should I get the data from server before starting Activity? Or the problem is something else? My php file is working okay when I check it in browser.

Here is onCreate Method:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.invoice_list);
    final ListView listView1 = (ListView) findViewById(R.id.invoicelist);
    InvoiceDownloader task = new InvoiceDownloader();

    task.execute(new String[] { "http://10.0.2.2/company/getinvoices.php" });
    ArrayAdapter<Invoice> adapter = new ArrayAdapter<Invoice>(this, android.R.layout.simple_list_item_1, invoices);
    listView1.setAdapter(adapter);
}

EDIT:

I fixed it as You all suggested, now there is no error, activity opens, but it still doesn't show any data from online database.. Here is edited onCreate() method:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.invoice_list);
    adapter = new ArrayAdapter<Invoice>(this, android.R.layout.simple_list_item_1);
    listView1 = (ListView) findViewById(R.id.invoicelist);
    InvoiceDownloader task = new InvoiceDownloader();
    task.execute(new String[] { "http://10.0.2.2/company/getinvoices.php" });
    adapter.notifyDataSetChanged();
}

and here is AsyncTask class:

public class InvoiceDownloader extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... params) {
        String response = "";
        try {
            response += getHttpContent(params[0]);
        } catch (IOException e) {
            Log.e("error", e.toString());
        }
        return response;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        adapter.addAll(invoices);
        listView1.setAdapter(adapter);

        Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
    }

    public String getHttpContent(String urlStr) throws IOException {

        String response = "";

        try {
            URL url = new URL(urlStr);
            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();

            StringBuilder sb = new StringBuilder();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
            String json;
            while ((json = bufferedReader.readLine()) != null) {
                sb.append(json + "\n");
            }

            JSONArray jsonArray = new JSONArray(sb.toString().trim());

            for (int i = 0; i < jsonArray.length(); i++) {
                Invoice invoice = new Invoice();
                JSONObject inv = jsonArray.getJSONObject(i);

                String companyNameOne = inv.getString("companyNameOne");
                String companyNameTwo = inv.getString("companyNameTwo");
                String address = inv.getString("address");
                String postalCode = inv.getString("postalCode");
                String city = inv.getString("city");
                String oib = inv.getString("oib");
                String email = inv.getString("email");
                int comple = inv.getInt("completed");
                String completed = String.valueOf(comple);
                String workOrderNumber = inv.getString("workOrderNumber");
                String price = inv.getString("price");

                System.out.println("Company Name 1: " + companyNameOne + " Company Name 2: " + companyNameTwo + " address: " + address + " postalCode: " + postalCode + " city: " + city + " oib: " + oib + " email: " + email + " completed: " + completed + " work order num: " + workOrderNumber + " price: " + price);

                invoice.setCompanyNameOne(companyNameOne);
                invoice.setCompanyNameTwo(companyNameTwo);
                invoice.setAddress(address);
                invoice.setPostalCode(postalCode);
                invoice.setCity(city);
                invoice.setOib(oib);
                invoice.setEmail(email);
                invoice.setCompleted(completed);
                invoice.setWorkOrderNumber(workOrderNumber);
                invoice.setPrice(price);

                invoices.add(invoice);
            }
            return response;
        } catch (Exception e) {
            return null;
        }
    }
}

2nd EDIT:

I got it. Sorry, this issue not showing data after fixing error was my mistake. In this part:

JSONObject inv = jsonArray.getJSONObject(i);

                String companyNameOne = inv.getString("companyNameOne");
                String companyNameTwo = inv.getString("companyNameTwo");
                String address = inv.getString("address");
                String postalCode = inv.getString("postalCode");
                String city = inv.getString("city");
                String oib = inv.getString("oib");
                String email = inv.getString("email");
                int comple = inv.getInt("completed");
                String completed = String.valueOf(comple);
                String workOrderNumber = inv.getString("workOrderNumber");
                String price = inv.getString("price");

those strings in (" ") ALL had to be small letters, because I wrote them that way in my PHP.

Thank You all for Your help.

Dimness
  • 162
  • 1
  • 13
  • Where did you initialize an invoices object? – Alex Nik Nov 14 '17 at 21:48
  • @Alex Nik On start, above onCreate method – Dimness Nov 14 '17 at 21:53
  • onStart calling after onCreate method. You should initialize collection before passing it to adapter – Alex Nik Nov 14 '17 at 21:56
  • Take a screenshot of your stack trace in logcat. It'll hopefully give us more info – Peter Chaula Nov 14 '17 at 22:16
  • And also, I suspect that you list is going to be empty because the adapter is not accessible in the INvoiceDownloader – Peter Chaula Nov 14 '17 at 22:17
  • @Mystiq please if you like/can come back with some feedback, did some solution work? – trocchietto Nov 15 '17 at 21:29
  • @trocchietto I added edit of onCreate and AsyncTask. There is no error anymore, but I still don't get the data from server. – Dimness Nov 16 '17 at 18:04
  • @Mystiq if you do not have the error anymore please accept `one` of the 3 answers, you liked the one that helped you more and also is possible to up vote the answers you liked more. I see you edited the post and now is working, I am glad you solved your challenge. – trocchietto Nov 16 '17 at 20:36

3 Answers3

1

Possibly you are not getting a reply from the server, and this is the reason why the list is null, edit posting the stacktrace and will able to help you better, have a look at this post it looks the same problem you had and the reason is in the call to the web service(SQL db) My guess is that the second line of your stacktrace says ArrayAdapter.getCount() because is usually here the problem, the method called by ArrayAdapter that returns a List, that in your case is null because does not retrieve from the Server. maybe a JsonException, so you should add an exception with a try catch to manage what happens if the server does not retrieve the response.

 public int   getCount() {


    return mObjects.size();

}

Async task is less used than 3 years ago, almost all the community uses now Retrofit to make asyncrous calls and also RXJava

trocchietto
  • 2,607
  • 2
  • 23
  • 36
1

you should set the data through adapter to listview on the onPostExecute() of the asyncTask. (https://developer.android.com/reference/android/os/AsyncTask.html)

Since the task is asynchronous, you are trying to access to the data of the invoices list, before the response from the server has arrived.

heisen
  • 1,067
  • 3
  • 9
  • 25
  • I marked this answer as closest to my solution, but all answer provided here were similar, and for me ALL are correct. Thanks once again to heisen , @trocchietto and Alex Nik . – Dimness Nov 16 '17 at 18:18
1

You are passing non initialized collection (null) into adapter. Thats why you are getting NullPointerException when adapter trying to get size of the collection. You need to do this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.invoice_list);
    ...
    invoices = new ArrayList<>();
    ArrayAdapter<Invoice> adapter = new ArrayAdapter<Invoice>(this, android.R.layout.simple_list_item_1, invoices);
    listView1.setAdapter(adapter);
}

and then populate collection with new items in onPostExecute of AsyncTask and call adapter.notifyDataSetChanged

Alex Nik
  • 753
  • 6
  • 15
  • I fixed it as You all suggested, not there is no error, it opens okay, but it still doesn't show any data from database – Dimness Nov 16 '17 at 18:00