使用 Volley 的后台服务出现 OutofMemory 错误

OutofMemory error on background service using Volley

我正在制作一个始终运行后台服务的应用程序。但问题是,几个小时后,它会抛出以下内存不足错误:

09-04 22:08:09.110  13810-13810/? I/art? Late-enabling -Xcheck:jni
09-04 22:08:09.165  13810-13810/com.mts.myapp I/MyService? FileScannerService Timer started....
09-04 22:08:10.265  13810-13834/com.mts.myapp I/art? Forcing collection of SoftReferences for 1GB allocation
09-04 22:08:10.280  13810-13834/com.mts.myapp E/art? Throwing OutOfMemoryError "Failed to allocate a 1627389964 byte allocation with 2648453 free bytes and 88MB until OOM"
09-04 22:08:10.310  13810-13834/com.mts.myapp I/art? Forcing collection of SoftReferences for 1GB allocation
09-04 22:08:10.350  13810-13834/com.mts.myapp E/art? Throwing OutOfMemoryError "Failed to allocate a 1627389964 byte allocation with 2648538 free bytes and 88MB until OOM"
09-04 22:08:10.355  13810-13834/com.mts.myapp E/AndroidRuntime? FATAL EXCEPTION: Thread-1654
    Process: com.mts.myapp, PID: 13810
    java.lang.OutOfMemoryError: Failed to allocate a 1627389964 byte allocation with 2648538 free bytes and 88MB until OOM
            at com.android.volley.toolbox.DiskBasedCache.streamToBytes(DiskBasedCache.java:316)
            at com.android.volley.toolbox.DiskBasedCache.readString(DiskBasedCache.java:526)
            at com.android.volley.toolbox.DiskBasedCache.readStringStringMap(DiskBasedCache.java:549)
            at com.android.volley.toolbox.DiskBasedCache$CacheHeader.readHeader(DiskBasedCache.java:392)
            at com.android.volley.toolbox.DiskBasedCache.initialize(DiskBasedCache.java:155)
            at com.android.volley.CacheDispatcher.run(CacheDispatcher.java:84)
09-04 22:08:25.260  13810-13949/com.mts.myapp I/art? Forcing collection of SoftReferences for 1GB allocation
09-04 22:08:25.280  13810-13949/com.mts.myapp E/art? Throwing OutOfMemoryError "Failed to allocate a 1627389964 byte allocation with 2651578 free bytes and 88MB until OOM"
09-04 22:08:25.310  13810-13949/com.mts.myapp I/art? Forcing collection of SoftReferences for 1GB allocation
09-04 22:08:25.330  13810-13949/com.mts.myapp E/art? Throwing OutOfMemoryError "Failed to allocate a 1627389964 byte allocation with 2651568 free bytes and 88MB until OOM"
09-04 22:08:25.330  13810-13949/com.mts.myapp I/Process? Sending signal. PID: 13810 SIG: 9

该服务在定义的时间间隔内使用 volleys 进行 Http 调用。检查返回的 JSONObject 并在必要时显示通知。

那么您认为是什么导致了内存不足错误?

这是截击:

RequestQueue queue = Volley.newRequestQueue(this);
        String url = "http://myrequesturl.com"
        StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {

                        //DO STUFF


                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                error.printStackTrace();
            }
        });
        queue.add(stringRequest);

某处内存泄漏。

这段代码似乎在每次调用时都会创建一个新的 RequestQueue,这不是 volley 的推荐方法。

您应该创建一个 RequestQueue,然后将我们的请求添加到这个队列中。

每次发出 http 请求时,您的服务都会创建新的请求队列,最好的方法是使用请求队列的单例对象并为每个请求重用它。

这是代码示例 //新建Java文件App.java

public class App extends Application {
    public static final String TAG = App.class.getSimpleName();
    private static App mInstance;

    private RequestQueue mRequestQueue;

    public static synchronized App getInstance() {
        return mInstance;
    }

    @Override
    public void onCreate() {

        super.onCreate();

        mRequestQueue = Volley.newRequestQueue(getApplicationContext());

        mInstance = this;

    }

    public RequestQueue getRequestQueue() {
        return mRequestQueue;
    }


    public <T> void addToRequestQueue(Request<T> request, String tag) {
        request.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(request);
    }

    public <T> void addToRequestQueue(Request<T> request) {
        request.setTag(TAG);
        getRequestQueue().add(request);
    }

    public void cancelPendingRequest(Object tag) {
        getRequestQueue().cancelAll(tag);
    }

}

// 在 android 中该应用程序的清单引用名称 class

 <application
        android:name=".App"
        ....

//现在只要你提出请求就这样做

App.getInstance().addToRequestQueue(stringRequest);

这将只创建一个请求队列实例并将其用于每个请求