【问题标题】:Volley crashing app on service after long run长期运行后,Volley 应用程序在服务中崩溃
【发布时间】:2018-08-25 05:59:43
【问题描述】:

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

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:致命异常:Timer-0 进程:com.mobiledatabook.com.dialcode,PID:11239 java.lang.OutOfMemoryError:pthread_create(堆栈大小 16384 字节) 失败:再试一次 在 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)

错误:java.lang.OutOfMemoryError。

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

【问题讨论】:

    标签: java android service out-of-memory android-volley


    【解决方案1】:

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

    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

    正如android官方文档here中提到的,

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

    【讨论】:

    • @JoDee 很高兴它有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    相关资源
    最近更新 更多