我正在开发我的第一个Android应用程序。我已经创建了一个Service类,其作用是检查外部网页上是否有任何新信息。 HTTP请求和服务正常工作,但过了一段时间我得到了这些OutOfMemoryError
。
有人能够看到服务收集所有内存的位置吗?
错误讯息1。
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 org.apache.http.impl.conn.tsccm.AbstractConnPool.enableConnectionGC(AbstractConnPool.java:140)
at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.createConnectionPool(ThreadSafeClientConnManager.java:120)
at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.(ThreadSafeClientConnManager.java:98)
at com.loopj.android.http.AsyncHttpClient.(AsyncHttpClient.java:210)
at com.loopj.android.http.AsyncHttpClient.(AsyncHttpClient.java:149)
at com.loopj.android.http.AsyncHttpClient.(AsyncHttpClient.java:119)
at com.quickit.app.MyService.checkUpdates(MyService.java:89)
at com.quickit.app.MyService.access$1(MyService.java:75)
at com.quickit.app.MyService$TimeDisplayTimerTask$1.run(MyService.java:68)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5105)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
at dalvik.system.NativeStart.main(Native Method)
错误讯息2。
java.lang.OutOfMemoryError: thread creation failed
at java.lang.VMThread.create(Native Method)
at java.lang.Thread.start(Thread.java:1050)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:913)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1295)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:81)
at com.loopj.android.http.AsyncHttpClient.sendRequest(AsyncHttpClient.java:893)
at com.loopj.android.http.AsyncHttpClient.post(AsyncHttpClient.java:688)
at com.loopj.android.http.AsyncHttpClient.post(AsyncHttpClient.java:671)
at com.loopj.android.http.AsyncHttpClient.post(AsyncHttpClient.java:658)
at com.quickit.app.MyService.checkUpdates(MyService.java:90)
at com.quickit.app.MyService.access$1(MyService.java:75)
at com.quickit.app.MyService$TimeDisplayTimerTask$1.run(MyService.java:68)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:5092)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:564)
at dalvik.system.NativeStart.main(Native Method)
我的服务类。
public class MyService extends Service {
boolean login = false;
// constant
public static final long NOTIFY_INTERVAL = 10 * 1000; // 10 seconds
String address = Utilities.getAPIUrl();
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
SharedPreferences prefs = getSharedPreferences("com.quickit.app", Context.MODE_PRIVATE);
login = prefs.getBoolean("login", false);
// cancel if already existed
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
public class TimeDisplayTimerTask extends TimerTask {
@Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
@Override
public void run() {
if(login) {
checkUpdates();
}
}
});
}
}
private void checkUpdates() {
final SharedPreferences prefs = getSharedPreferences("com.quickit.app", Context.MODE_PRIVATE);
final String from_id = prefs.getInt("user", 0)+"";
final String lastCheck = prefs.getString("last_check", "0");
RequestParams params = new RequestParams();
params.put("type", "get_ask_questions");
params.put("fromid", from_id);
params.put("last_check", lastCheck);
AsyncHttpClient client = new AsyncHttpClient();
client.post(address, params, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(String response) {
try {
notification(response);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
答案 0 :(得分:6)
每次计时器到期时,您的代码都会不断创建新的AsyncHttpClient对象!如果对象永远不会完成它的工作,那么在某些时候,你将会耗尽内存。
由于您只是定期检查更新,因此您应该将AsyncHttpClient对象设置为静态,然后重复使用它。
具体来看http://loopj.com/android-async-http/,推荐用法部分。