I am doing long polling in my app, checking for new data every 500ms then update my textview when there is a new change. It's doing fine but after a few minutes, my app just crashes and gives me this error:
java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Try again
at java.lang.Thread.nativeCreate(Native Method)
at java.lang.Thread.start(Thread.java:1063)
at com.android.volley.RequestQueue.start(RequestQueue.java:142)
at com.android.volley.toolbox.Volley.newRequestQueue(Volley.java:66)
at com.android.volley.toolbox.Volley.newRequestQueue(Volley.java:78)
at com.example.rendell.longpolling.MainActivity.sendRequest(MainActivity.java:96)
at com.example.rendell.longpolling.MainActivity$1$1.run(MainActivity.java:59)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5253)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:900)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:695)
MainActivity.java
public class MainActivity extends AppCompatActivity {
TextView text;
Date noteTS;
public static final String JSON_URL = "http://192.168.0.100/androidphp/data.php";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
(new Thread(new Runnable()
{
@Override
public void run()
{
while (!Thread.interrupted())
try
{
Thread.sleep(500);
runOnUiThread(new Runnable() // start actions in UI thread
{
@Override
public void run()
{
// this action have to be in UI thread
/*noteTS = Calendar.getInstance().getTime();
String time = "hh:mm"; // 12:00
text.setText(DateFormat.format(time, noteTS));*/
sendRequest();
}
});
}
catch (InterruptedException e)
{
// ooops
}
}
})).start(); // the while thread will start in BG thread
}
public void sendRequest(){
//While the app fetched data we are displaying a progress dialog
//final ProgressDialog loading = ProgressDialog.show(this,"Fetching Data","Please wait...",false,false);
StringRequest stringRequest = new StringRequest(JSON_URL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//text.setText(response);
//loading.dismiss();
try{
showJSON(response);
}catch(Exception e) {}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_LONG).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
private void showJSON(String json){
ParseJson pj = new ParseJson(json);
pj.parseJSON();
text.setText(ParseJson.playing[0]);
}
}
ParseJson.java
public class ParseJson {
public static String[] playing;
public static final String JSON_ARRAY = "result";
public static final String RESULT_ID = "playing";
private JSONArray users = null;
private String json;
public ParseJson(String json){
this.json = json;
}
public void parseJSON(){
JSONObject jsonObject=null;
try {
jsonObject = new JSONObject(json);
users = jsonObject.getJSONArray(JSON_ARRAY);
playing = new String[users.length()];
for(int i=0;i<users.length();i++){
JSONObject jo = users.getJSONObject(i);
playing[i] = jo.getString(RESULT_ID);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
I'm not sure what is wrong with your code but I can give you few tips
first of all, Read the android documentations on how to make a singleton class for volley, you are creating a new RequestQueue every time you send a request, I use one queue for my whole app, maybe in some cases you create more but I can't think of any right now, most probably this is your main problem since the error is happening at newQueue method
you don't have to make the singleton class but at least try to make the queue as instance variable and add to it each time.
second of all there are simpler ways to perform a task every x seconds, I heared (NOT SURE) that using thread.sleep in android is not recommended
here is how I usually perform such tasks:
Timer timer = new Timer();
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
// do something on UI
}
};
TimerTask task = new TimerTask () {
@Override
public void run () {
//send volley request here
}
};
timer.schedule(task, 0, 60000); // 60000 is time in ms