0

Code

public class OrderTableActivity extends AppCompatActivity {

private  List<String> bidList = new ArrayList<>();
private List<String> askList = new ArrayList<>();
private  RecyclerView recyclerView;
private OrderTableAdapter adapter;
private BidsAsks bidsAsks;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_order_table);

    bidsAsks = populateLists(); //makes async call and gets data from API and stores in BidsAsks object

    recyclerView=(RecyclerView)findViewById(R.id.recyclerView);
    adapter = new OrderTableAdapter(OrderTableActivity.this);
    recyclerView.setLayoutManager(new LinearLayoutManager(OrderTableActivity.this));
    recyclerView.setAdapter(adapter);

    populate(); //populates the data lists
    adapter.setItemList(bidList, askList);
    Log.i("TAG", "oncreate complete");
   // adapter.notifyDataSetChanged();

}

//get data dummy``
private List<String> getData() {

    List<String> data = new ArrayList<>();
    for(int i=0; i<20; i++){
        data.add("A"+i);
    }
    return data;
}

private void populate(){
    List<List<String>> bids = bidsAsks.getBids(); //NULL pointer exception
    List<List<String>> asks = bidsAsks.getAsks();


    for(int i=0; i<100 && i<asks.size() ;i++){
        //get ith list

        String bid_value = bids.get(i).get(0);
        String ask_value = asks.get(i).get(0);
        //Log.i("X", bid_value);
        //Log.i("X", ask_value);

        bidList.add(bid_value);
        askList.add(ask_value);
        //dataList.add(map);
    }

    Log.i("size", bidList.size()+"");
    Log.i("size", askList.size()+"");

}

//works fine and gets the data and stores in the object
private BidsAsks populateLists(){
    Retrofit retrofit = RetrofitClientInstance.getRetrofitInstance();

    JsonPlaceholderApi jsonPlaceholderApi = retrofit.create(JsonPlaceholderApi.class);


    Call<BidsAsks> call = jsonPlaceholderApi.getBidsAndAsksData();
    call.enqueue(new Callback<BidsAsks>() {
        @Override
        public void onResponse(Call<BidsAsks> call, Response<BidsAsks> response) {

            if(response.isSuccessful()){

                bidsAsks = response.body();
                Log.i("TAG", bidsAsks.toString()+" found");

            }else{
                Log.i("err", "err while parsing");
            }
        }

        @Override
        public void onFailure(Call<BidsAsks> call, Throwable t) {

        }
    });


    return bidsAsks;
 }
}

Error

Error: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.cryptoinfo/com.example.cryptoinfo.OrderTableActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.example.cryptoinfo.BidsAsks.getBids()' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7356) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.example.cryptoinfo.BidsAsks.getBids()' on a null object reference at com.example.cryptoinfo.OrderTableActivity.populate(OrderTableActivity.java:62) at com.example.cryptoinfo.OrderTableActivity.onCreate(OrderTableActivity.java:36) at android.app.Activity.performCreate(Activity.java:7802) at android.app.Activity.performCreate(Activity.java:7791) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)  at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)  at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)  at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)  at android.os.Handler.dispatchMessage(Handler.java:107)  at android.os.Looper.loop(Looper.java:214)  at android.app.ActivityThread.main(ActivityThread.java:7356)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)  I/Process: Sending signal. PID: 1078 SIG: 9 Process 1078 terminated.

Afia
  • 683
  • 5
  • 17
Learner
  • 61
  • 1
  • 7
  • 1
    Why do you believe `bidsAsks` isn't `null`? It is only ever assigned in the `onResponse` **callback** method, and the **asynchronous** call hasn't completed yet, so the callback method hasn't been invoked yet. – Andreas Jan 26 '20 at 03:01
  • I printed the value in onResponse() and it gave correct data values and after that it printed the Log "oncreate complete", Could you help me rectify the code? – Learner Jan 26 '20 at 03:06
  • 1
    I'm sorry, that is **impossible**, because if you get that `NullPointerException`, then the `populate()` call failed and the `oncreate complete` log statement 2 lines down wouldn't be executed, so there is **absolutely** no way for both to happen for the same `OrderTableActivity` object. – Andreas Jan 26 '20 at 03:11
  • Ya that's right, I commented out the populate part to see if populateLists() was able to get the data from API and then finish the async call and go back to oncreate and that part worked. But when I tried to decomment the populate() to get the data from object, it threw an exception. So, I cannot figure out why it could not get the data from object if the object got the value from async call and wasn't null upon returning to onCreate() – Learner Jan 26 '20 at 03:15
  • 2
    Assume for a second that the call is very slow, e.g. it takes 10 seconds between `call.enqueue(...)` being invoked by you and the `onResponse(...)` method being called back. Since `enqueue(...)` doesn't wait and returns immediately, `populateLists()` returns immediately, and `populate();` is called very shortly thereafter, definitely way before 10 seconds has elapsed, so `bidsAsks.getBids()` will fail with `NullPointerException`. --- *Sometimes*, the callback might happen very quickly, sometimes it's slow. This is called a **race condition**. – Andreas Jan 26 '20 at 03:23
  • Oh, that makes sense, so like how to go about dealing with this, how do I make the main thread wait till it receives the data but without freezing the UI – Learner Jan 26 '20 at 03:27
  • 2
    "without freezing the UI" = "don't make it wait" = "anything using `bidsAsks` must be executed in/after the `onResponse` event" – Andreas Jan 26 '20 at 03:31
  • Objects are never null, but references are. – user207421 Jan 26 '20 at 03:46

0 Answers0