Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialjustin z
11,042 PointsProblem with OkHttp...
I was making an app that uses OkHttp to get Chuck Norris facts from chucknorris.io, but was having some problems using OkHttp. My error is caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
Thanks!
6 Answers
aakarshrestha
6,509 PointsMake the String permission public, not private.
private String mChuckData;
Change it to:
public String mChuckData;
Also do the debugging by adding Log.v statement on
mChuckData = response.body().string();
Log.v("CheckData", mChuckData);
If you see the data in the Log.v statement in the console, then it is working. From this point on, you should be able to figure out why it is throwing NullPointerException.
Hope it helps!
Happy coding!
justin z
11,042 PointsI am able to see the Log.v statement in the console.
My console is leading me to believe the mistake is somewhere in the setFact() method, but I can't figure out why there is an issue since mChuckData isn't null.
aakarshrestha
6,509 PointsGet rid of this statement, you are just passing string to the method where string does not have any value in it.
try {
setFact();
} catch (JSONException e) {
e.printStackTrace();
}
Make your onResponse method like this:
public void onResponse(Call call, final Response response) throws IOException {
mChuckData = response.body().string();
JSONObject jsonObject = new JSONObject(mChuckData);
mChuckFact = jsonObject.getString("value");
}
I see that in your setFact() has no String parameter and you are passing
JSONObject jsonObject = new JSONObject(mChuckData); -> mChuckData, which is empty.
Hope it helps!
Happy Coding!
justin z
11,042 PointsThis fix worked, thank you! But I have one more question: why is mChuckData empty? It's a member variable and doGetRequest() is called before setFact(), so I don't see why it was empty.
Philip Gales
15,193 Pointsyour get request is on a different, slower thread.
aakarshrestha
6,509 PointsTry this, it should solve your problem:
package justinzwick.chucknorrisfacts;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class FactActivity extends AppCompatActivity {
private OkHttpClient client = new OkHttpClient();
public String mChuckData;
private TextView mFactText;
private String mChuckFact;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fact);
mFactText = (TextView) findViewById(R.id.factText);
try {
doGetRequest("https://api.chucknorris.io/jokes/random");
} catch (IOException e) {
e.printStackTrace();
}
}
public void doGetRequest(String url) throws IOException{
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request)
.enqueue(new Callback() {
@Override
public void onFailure(final Call call, IOException e) {
// Error
runOnUiThread(new Runnable() {
@Override
public void run() {
// For the example, you can show an error dialog or a toast
// on the main UI thread
Toast.makeText(FactActivity.this, "there was an error", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
mChuckData = response.body().string();
JSONObject jsonObject = new JSONObject(mChuckData);
mChuckFact = jsonObject.getString("value");
}
});
}
}
Hope it helps!
Happy Coding!
aakarshrestha
6,509 PointsString that you are passing in the JSONObject inside your setFact is empty.
In the onResponse method, you have the value stored in mChuckData but it is not passed to the setFact() method because setFact() method is not taking any argument.
Inside the setFact() method, you passed mChuckData, which is declared on the top of your create method and it is private. You are calling setFact() method separately which does not have any value passed in it.
So if you change your setFact() method to setFact(String mChuckData) and call this method inside your onResponse method where you are storing data coming from the webservice call.
Call it in this way:
public void onResponse(Call call, final Response response) throws IOException {
mChuckData = response.body().string();
setFact(mChuckData);
}
Change your setFact() method to:
public void setFact(String mchuckdata) throws JSONException {
JSONObject jsonObject = new JSONObject(mchuckdata);
mChuckFact = jsonObject.getString("value");
}
Hope it make sense to you now.
Happy coding!
justin z
11,042 PointsPhilip Gales, here is the whole error:
06-18 13:50:05.756 11626-11626/justinzwick.chucknorrisfacts E/AndroidRuntime: FATAL EXCEPTION: main Process: justinzwick.chucknorrisfacts, PID: 11626 java.lang.RuntimeException: Unable to start activity ComponentInfo{justinzwick.chucknorrisfacts/justinzwick.chucknorrisfacts.FactActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3254) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) at android.app.ActivityThread.access$1100(ActivityThread.java:222) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7229) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference at org.json.JSONTokener.nextCleanInternal(JSONTokener.java:116) at org.json.JSONTokener.nextValue(JSONTokener.java:94) at org.json.JSONObject.<init>(JSONObject.java:156) at org.json.JSONObject.<init>(JSONObject.java:173) at justinzwick.chucknorrisfacts.FactActivity.setFact(FactActivity.java:73) at justinzwick.chucknorrisfacts.FactActivity.onCreate(FactActivity.java:36) at android.app.Activity.performCreate(Activity.java:6876) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) at android.app.ActivityThread.access$1100(ActivityThread.java:222) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7229) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Philip Gales
15,193 PointsIs your doGetRequest() getting a response, or is it showing your Toast? I am assuming it either is not getting a response or, because it is on a slower thread that the setFact() is beating it.
Try moving your setFact to your response block of code.
try {
setFact();
} catch (JSONException e) {
e.printStackTrace();
}
justin z
11,042 PointsThe app would crash as soon as I would open it, so I would never see the toast. I made the fix that Aakar suggested and now the app works fine, but I'm not completely sure why it works now. Do you know why the mChuckData that I was passing into the JSONObject was null? I don't see how it could be null since I called doGetRequest() before setFact().
Philip Gales
15,193 PointsIt is null, because even though you are calling the doGetRequest() first, it is on a different thread and takes much longer to finish. While it is running on that thread, the main thread has already called setFact(). In the videos they explain threads and how the main thread is faster than the other threads.
justin z
11,042 PointsOk, thanks! I will watch the treehouse lessons on threads so I can understand this further.
Philip Gales
15,193 PointsPhilip Gales
15,193 PointsCan you paste the whole error?