-2

I have an activity and am getting a nullPointerException on the last line of the clicked method

public class MainActivity extends AppCompatActivity {

List<Item> it;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);   
    }

    public void clicked(View view) {          
        getCompany(s);
        Integer.toString(it.size());  
    }

    public void getCompany(String name) {

        apiCall.setCallback(new ApiCall.NetworkCallback() {
            @Override
            public void onResponse(List<Item> items) {
                 it = items;
                for (int i = 0; i < items.size(); i++) {    
                    Log.d("Name", it.get(i).getTitle());
                }
            }
        });
    }

I have removed some of the code to keep it short but the issue is the 'it' list is accessible in the onResponse method but gives a nullPointerException in the clicked method.

What would be causing this and how can I store the list to be used outside of the onResponse method?

Struggler
  • 1
  • 2
  • 1
    Also, when you have an `Exception`, always include the stack trace and highlight the line(s) causing the exception. And you may want to learn [how to debug your program](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). – Turing85 Feb 10 '19 at 21:01
  • @Carcigenicate, onResponse is called from within clicked, before i get the exception – Struggler Feb 10 '19 at 21:17

4 Answers4

1

because you try to get size of list before initialize it . in Integer.toString(it.size());
because it not initialized yet getCompany(s); is asynchronous method try to remove Integer.toString(it.size());
because in not used and not useful. public class MainActivity extends AppCompatActivity {

List<Item> it;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);   
}

public void clicked(View view) {          
    getCompany(s);
}

public void getCompany(String name) {

    apiCall.setCallback(new ApiCall.NetworkCallback() {
        @Override
        public void onResponse(List<Item> items) {
             it = items;
            for (int i = 0; i < items.size(); i++) {    
                Log.d("Name", it.get(i).getTitle());
            }
        }
    });
}
  • Yes I know its not used and its not useful. I want to store the List in the activity. That line was just to see if the List exists, which it does not. Also, I can use the it List from the onResponse method before the line in question – Struggler Feb 10 '19 at 21:23
0

In clicked you call getCompany where you set a callback where it is set. Problem is that onResponse will most likely be called some time after that and apiCall.setCallback will return immediately. So getCompany returns immediately and it will still be null when you try to access it.

Whatever you want to do after doResponse is called, it should be initiated in doResponse. How to do that depends on the actual use case which is not clear with your example but maybe my explanation helps you to have some ideas for yourself. If not, start a new question here with more details (new question because it has nothing to do with NullPointerExceptions).

Lothar
  • 5,323
  • 1
  • 11
  • 27
  • Okay thanks for the answer. I guess I can do what I want to do in onResponse, I just wanted to store the List in the activity first – Struggler Feb 10 '19 at 21:20
0

I'll go straight with a possible solution for you which give you a quick example of an interface

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);   
    }

    public void clicked(View view) {          
        getCompany(s, new OnReceiveCompany() {
            @Override
            public void onReceiveCompany(List<Item> it) {
                Integer.toString(it.size());                  
            }
        });
    }

    public void getCompany(String name, final OnReceiveCompany callback) {
        apiCall.setCallback(new ApiCall.NetworkCallback() {
            @Override
            public void onResponse(List<Item> items) {
                for (int i = 0; i < items.size(); i++) {    
                    Log.d("Name", it.get(i).getTitle());
                }
                // make sure this run on UI thread if you need to perform ui operation. You can wrap it with new Hanler(Looper.getMainLooper).post(...
                callback.onReceiveCompany(items);
            }
        });
    }

    interface OnReceiveCompany {
        void onReceiveCompany(List<Item> it);
    } 
}

why your code is not working:

    public void clicked(View view) {
        // this method is gonna set "it" in the block of code in onResponse, which will happens after you call Integer.toString probably in a separate thread
        getCompany(s);
        Integer.toString(it.size());  
    }
iGio90
  • 290
  • 1
  • 4
  • 15
  • Thanks for that. Interfaces seem to be the solution to a lot of problems I've been having with android. I will try it tomorrow – Struggler Feb 10 '19 at 21:27
0

A NullPointerException occurs when you try to use a null variable (or a variable that has not been initialized).

Even though onResponse() is called from within clicked(), you have to remember that onResponse is within an asynchronous call. This simply means that it is not guaranteed that onResponse would finish executing before clicked() is called.

I'd suggest adding Integer.toString(it.size()) to your onResponse() method.

I hope this helps. Struggle no more ;-) Merry coding!

Taslim Oseni
  • 6,086
  • 10
  • 44
  • 69
  • thanks for the reply but it does not help me. I want to store the list in the activity. I was only calling the size method to see if the List existed. – Struggler Feb 10 '19 at 21:30