长时间运行后,Volley 应用程序崩溃 [英] Volley crashing app on service after long run

查看:18
本文介绍了长时间运行后,Volley 应用程序崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实施一项服务以从服务器获取更新,如下所示:

Am implementing a service to get updates from server as below:

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;
    }

}

但是,在长时间运行该服务后,该应用程序崩溃并显示以下错误:

However, after a long running of the service the app is crashing with the below error:

03-08 00:19:41.570 11239-11253/com.mobiledatabook.com.dialcodeE/AndroidRuntime:致命异常:Timer-0进程:com.mobiledatabook.com.dialcode,PID:11239java.lang.OutOfMemoryError: pthread_create (stack size 16384 bytes)失败:再试一次在 java.lang.VMThread.create(本机方法)在 java.lang.Thread.start(Thread.java:1029)在 com.android.volley.RequestQueue.start(RequestQueue.java:152)在 com.android.volley.toolbox.Volley.newRequestQueue(Volley.java:66)在 com.android.volley.toolbox.Volley.newRequestQueue(Volley.java:78)在com.mobiledatabook.com.dialcode.Myupdates.iDialAutoUpdates(Myupdates.java:128)在com.mobiledatabook.com.dialcode.Myupdates$1$1.run(Myupdates.java:74)在 java.util.Timer$TimerImpl.run(Timer.java:284)

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$1$1.run(Myupdates.java:74) at java.util.Timer$TimerImpl.run(Timer.java:284)

错误:java.lang.OutOfMemoryError.

Error: java.lang.OutOfMemoryError.

有人可以帮我改进这段代码,以避免在长时间运行服务后应用程序崩溃吗?

Could someone help me to improve this code so as to avoid crashing the app after long running of the service?

推荐答案

发生这种情况是因为您通过传递活动 context 多次创建 RequestQueue 实例.您应该使用 Application 类创建一次实例,然后在需要时一次又一次地使用它.像这样创建一个应用程序类,

This is occurring because you are creating the RequestQueue instance multiple times by passing the activity context. You should create the instance once using an Application class and then use it again and again whenever needed. Create an application class like this,

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 当无法分配更多空间时

NOTE : By passing the context to request queue again and again , you are filling up your ram, which leads to an OutOfMemoryException when no more space can be allocated

如 android 的官方文档中所述此处

As mentioned in android's official docs here ,

一个关键概念是 RequestQueue 必须使用 Application 上下文而不是 Activity 上下文进行实例化.这可确保 RequestQueue 将在您的应用程序的整个生命周期内持续使用,而不是在每次重新创建 Activity 时(例如,当用户旋转设备时)重新创建.

A key concept is that the RequestQueue must be instantiated with the Application context, not an Activity context. This ensures that the RequestQueue will last for the lifetime of your app, instead of being recreated every time the activity is recreated (for example, when the user rotates the device).

这篇关于长时间运行后,Volley 应用程序崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆