Home » Android » Prevent crashing while heavy process

Prevent crashing while heavy process

Posted by: admin November 1, 2017 Leave a comment

Questions:

I am making a Map based app where users would often load over 10k polygons on the map. The only problem is that the only way to add a polygon to the map is in the UI thread, which means when I add them it will either freeze for 5 – 10 seconds or it will crash.

I’m ready to accept that it will just have to take time to load, but is there a way I can slow down the for loop when the system is struggling to prevent the crashing and even the freezing? One method I have thought of is putting a short delay on the for loop, but that will be less than ideal as it will have to take much longer then it has to to be on the safe side.

          protected void onPostExecute(HashMap<String, ArrayList> result){
            for(String key : result.keySet()){
                List<PolygonOptions> thisList = result.get(key);
                for(PolygonOptions poly: thisList){
                    Polygon thisPoly = mMap.addPolygon(poly);
                }
            }
          }
Answers:

Here there is a pseudo code about how I solve this:

private final Handler handler_render_data = new Handler ();
private int actualItemRendering;
private static final int HANDLER_RUN_DELAY = 1000;



    @Override
protected void onCreate(Bundle savedInstanceState)  {
    super.onCreate(savedInstanceState);

    //  Display the message telling the user to wait
    //  This Linear Layout includes a text and cover all teh screen
    lyt_report_progress = (LinearLayout) findViewById (R.id.lyt_report_progress);
    lyt_report_progress.setVisibility (View.VISIBLE);
    lyt_report_progress.requestFocus ();
    lyt_report_progress.setClickable (true);

    //  Your code calling your async task

}

//  Your callback from your async task
private void callbackHere (Data myData) {

    this.localMyData = myData;

    //  You store your data locally and start the rendering process
    actualItemRendering = 0;
    handler_render_data.post (createDataFromTaskResult);
}


private Runnable createDataFromTaskResult = new Runnable () {

    @Override
    public void run () {

        if (actualItemRendering < myData.length ()) {

            //  Render your data here

            //  Continue with the next item to render
            actualItemRendering++;
            handler_render_data.post (createDataFromTaskResult);

        } else {
            //  All fields were rendered
            handler.postDelayed (hideProgressBarTask, HANDLER_RUN_DELAY);
        }
    }
};

private Runnable hideProgressBarTask = new Runnable () {

    @Override
    public void run () {

        lyt_report_progress.setVisibility (View.GONE);

    }
};

Hope it helps you.

Questions:
Answers:

Split it into several tasks and execute each task on main thread separately. I.e.

for (int i = 0; i < 20; ++i) {
    runOnUiThread(new Runnable() { .. process 1/20 of your work });
}

You don’t need to add a delay. Also you can experiment with granularity, probably better to increase it from 1/20.