长时间 运行 后 Volley 在服务中崩溃
Volley crashing app on service after long run
正在实施一项服务以从服务器获取更新,如下所示:
public class Myupdates extends Service {
private static final String TAG = "AutoUpdates";
private static final int started = 0;
static SQLiteDatabase db;
private boolean isRunning = false;
private CountDownTimer timer;
@Override
public void onCreate() {
this.db = openOrCreateDatabase("db", Context.MODE_PRIVATE, null);
//Log.i(TAG, "Service onCreate");
isRunning = true;
}
int mCount = 1;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Log.i(TAG, "Service onStartCommand");
//Creating new thread for my service
//Always write your long running tasks in a separate thread, to avoid ANR
new Thread(new Runnable() {
@Override
public void run() {
if (isRunning) {
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
updates();
}
}, 0, 30000);
}
//Stop service once it finishes its task
//stopSelf();
}
}).start();
return Service.START_STICKY;
}
@Override
public IBinder onBind(Intent arg0) {
//Log.i(TAG, "Service onBind");
return null;
}
@Override
public void onDestroy() {
isRunning = false;
//Log.i(TAG, "Service onDestroy");
}
/*
HANDLE ADVERTS
*/
protected void updates() {
/*
JSON
*/
final JSONObject json = new JSONObject();
final JSONObject manJson = new JSONObject();
try {
manJson.put("userid", "4444");
manJson.put("version", "6.0");
final String j = json.put("UPDATE", manJson).toString();
final String base_url = "https://myweburl.com";
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.POST, base_url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//Log.i(TAG, "received "+response);
try {
JSONObject object = (JSONObject) new JSONTokener(response).nextValue();
String update = object.getString("UPDATE");
} catch (JSONException e) {
return;
}
return;
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//perform operation here after getting error
return;
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
//pack message into json
try {
params.put("data", j.toString());
} catch (Exception e) {
//Log.i(TAG,"Map error: Unable to compile post");
}
return params;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
};
// Add the request to the RequestQueue.
queue.add(stringRequest);
// ends here
return;
} catch (Exception e) {
//Log.i(TAG,"ERROR: Unable to get setup settings");
} // end exception write
return;
}
}
但是,在长时间 运行 服务后,应用程序崩溃并出现以下错误:
03-08 00:19:41.570 11239-11253/com.mobiledatabook.com.dialcode
E/AndroidRuntime: FATAL EXCEPTION: Timer-0
Process: com.mobiledatabook.com.dialcode, PID: 11239
java.lang.OutOfMemoryError: pthread_create (stack size 16384 bytes)
failed: Try again
at java.lang.VMThread.create(Native Method)
at java.lang.Thread.start(Thread.java:1029)
at com.android.volley.RequestQueue.start(RequestQueue.java:152)
at com.android.volley.toolbox.Volley.newRequestQueue(Volley.java:66)
at com.android.volley.toolbox.Volley.newRequestQueue(Volley.java:78)
at
com.mobiledatabook.com.dialcode.Myupdates.iDialAutoUpdates(Myupdates.java:128)
at
com.mobiledatabook.com.dialcode.Myupdates.run(Myupdates.java:74)
at java.util.Timer$TimerImpl.run(Timer.java:284)
Error: java.lang.OutOfMemoryError.
有人可以帮助我改进此代码,以避免在长时间 运行 服务后应用程序崩溃吗?
发生这种情况是因为您通过传递 activity context
多次创建 RequestQueue
实例。您应该使用 Application class 创建一次实例,然后在需要时一次又一次地使用它。像这样创建一个应用程序class,
public class AppController extends Application {
private static AppController sInstance;
private RequestQueue mRequestQueue;
@Override
public void onCreate() {
super.onCreate();
sInstance = this;
}
public static synchronized AppController getInstance() {
return sInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
}
那就这样用吧
RequestQueue queue=AppController.getInstance().getRequestQueue();
注意 :通过一次又一次地将上下文传递给请求队列,您正在填满您的 ram,这导致 OutOfMemoryException
当不再 space 可以分配
如 android 的官方文档 here 所述,
一个关键概念是 RequestQueue
必须用 Application
上下文实例化,而不是 Activity
上下文。这确保 RequestQueue
将在您的应用程序的整个生命周期内持续存在,而不是在每次重新创建 activity 时都重新创建(例如,当用户旋转设备时)。
正在实施一项服务以从服务器获取更新,如下所示:
public class Myupdates extends Service {
private static final String TAG = "AutoUpdates";
private static final int started = 0;
static SQLiteDatabase db;
private boolean isRunning = false;
private CountDownTimer timer;
@Override
public void onCreate() {
this.db = openOrCreateDatabase("db", Context.MODE_PRIVATE, null);
//Log.i(TAG, "Service onCreate");
isRunning = true;
}
int mCount = 1;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Log.i(TAG, "Service onStartCommand");
//Creating new thread for my service
//Always write your long running tasks in a separate thread, to avoid ANR
new Thread(new Runnable() {
@Override
public void run() {
if (isRunning) {
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
updates();
}
}, 0, 30000);
}
//Stop service once it finishes its task
//stopSelf();
}
}).start();
return Service.START_STICKY;
}
@Override
public IBinder onBind(Intent arg0) {
//Log.i(TAG, "Service onBind");
return null;
}
@Override
public void onDestroy() {
isRunning = false;
//Log.i(TAG, "Service onDestroy");
}
/*
HANDLE ADVERTS
*/
protected void updates() {
/*
JSON
*/
final JSONObject json = new JSONObject();
final JSONObject manJson = new JSONObject();
try {
manJson.put("userid", "4444");
manJson.put("version", "6.0");
final String j = json.put("UPDATE", manJson).toString();
final String base_url = "https://myweburl.com";
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.POST, base_url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//Log.i(TAG, "received "+response);
try {
JSONObject object = (JSONObject) new JSONTokener(response).nextValue();
String update = object.getString("UPDATE");
} catch (JSONException e) {
return;
}
return;
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//perform operation here after getting error
return;
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
//pack message into json
try {
params.put("data", j.toString());
} catch (Exception e) {
//Log.i(TAG,"Map error: Unable to compile post");
}
return params;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
};
// Add the request to the RequestQueue.
queue.add(stringRequest);
// ends here
return;
} catch (Exception e) {
//Log.i(TAG,"ERROR: Unable to get setup settings");
} // end exception write
return;
}
}
但是,在长时间 运行 服务后,应用程序崩溃并出现以下错误:
03-08 00:19:41.570 11239-11253/com.mobiledatabook.com.dialcode E/AndroidRuntime: FATAL EXCEPTION: Timer-0 Process: com.mobiledatabook.com.dialcode, PID: 11239 java.lang.OutOfMemoryError: pthread_create (stack size 16384 bytes) failed: Try again at java.lang.VMThread.create(Native Method) at java.lang.Thread.start(Thread.java:1029) at com.android.volley.RequestQueue.start(RequestQueue.java:152) at com.android.volley.toolbox.Volley.newRequestQueue(Volley.java:66) at com.android.volley.toolbox.Volley.newRequestQueue(Volley.java:78) at com.mobiledatabook.com.dialcode.Myupdates.iDialAutoUpdates(Myupdates.java:128) at com.mobiledatabook.com.dialcode.Myupdates.run(Myupdates.java:74) at java.util.Timer$TimerImpl.run(Timer.java:284)
Error: java.lang.OutOfMemoryError.
有人可以帮助我改进此代码,以避免在长时间 运行 服务后应用程序崩溃吗?
发生这种情况是因为您通过传递 activity context
多次创建 RequestQueue
实例。您应该使用 Application class 创建一次实例,然后在需要时一次又一次地使用它。像这样创建一个应用程序class,
public class AppController extends Application {
private static AppController sInstance;
private RequestQueue mRequestQueue;
@Override
public void onCreate() {
super.onCreate();
sInstance = this;
}
public static synchronized AppController getInstance() {
return sInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
}
那就这样用吧
RequestQueue queue=AppController.getInstance().getRequestQueue();
注意 :通过一次又一次地将上下文传递给请求队列,您正在填满您的 ram,这导致 OutOfMemoryException
当不再 space 可以分配
如 android 的官方文档 here 所述,
一个关键概念是 RequestQueue
必须用 Application
上下文实例化,而不是 Activity
上下文。这确保 RequestQueue
将在您的应用程序的整个生命周期内持续存在,而不是在每次重新创建 activity 时都重新创建(例如,当用户旋转设备时)。