Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android load multiple markers block my UI

i have around 11000 markers in markerarray list, when i try to load in map it blocks my UI, even when i use Thread and RunOnUi thread, is there any other better way i can try ??

 Thread t = new Thread(new Runnable() {

                @Override
                public void run() {
                    for (int i = 0; i < list.size(); i++) {

                        markerOptionList.add(new MarkerOptions().position(
                                new LatLng(Double.parseDouble(list.get(i)
                                        .getLatitude()), Double
                                        .parseDouble(list.get(i)
                                                .getLangtitude()))).title(
                                list.get(i).getName() + "~"
                                        + list.get(i).getCity() + "~"
                                        + list.get(i).getSector() + "~"
                                        + String.valueOf(false)));
                    }

                    getActivity().runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            addMarker();
                        }
                    });

                }
            });
            t.start();

add marker is my method where i added marker in map

Kindly suggest better way to implement Thanks in advance

like image 635
Madhu Avatar asked Jun 29 '15 05:06

Madhu


2 Answers

With such amount of markers as you mentioned (11000) it is highly advisable to use Marker Clustering. You can read more about it on: https://developers.google.com/maps/documentation/android-api/utility/marker-clustering

If you still want to do this without Marker Clustering there is a simple trick that can improve user experience.

As adding a marker modifies UI - it has to be done in main UI thread. Adding too much of them at one time blocks the main thread so that the application does not respond to any user actions while it is busy with adding markers. The end user may feel like the application has hung or stopped or it can even lead to ANR

The trick is to add the markers gradually, leaving some breaks for main thread to handle other actions, so that the application remains responsive for whole the time.

I would suggest such approach:

public class DrawMarkersTask extends AsyncTask<Void, MarkerOptions, Void> {
    protected void onPreExecute() {
        // this method executes in UI thread
        googleMap.clear(); // you can clear map here for example
    }

    @Override
    protected Void doInBackground(Void... params) {
        // this method executes in separate background thread
        // you CANT modify UI here
        for (int i = 0; i < list.size(); i++) {
            // prepare your marker here
            MarkerOptions markerOptions = new MarkerOptions().position(
                            new LatLng(Double.parseDouble(list.get(i)
                                    .getLatitude()), Double
                                    .parseDouble(list.get(i)
                                            .getLongtitude()))).title(
                            list.get(i).getName() + "~"
                                    + list.get(i).getCity() + "~"
                                    + list.get(i).getSector() + "~"
                                    + String.valueOf(false)));

            publishProgress(markerOptions); // pass it for the main UI thread for displaying
            try {
                Thread.sleep(50); // sleep for 50 ms so that main UI thread can handle user actions in the meantime
            } catch (InterruptedException e) {
                // NOP (no operation)
            }
        }
        return null;
    }

    protected void onProgressUpdate(MarkerOptions... markerOptions) {
        // this executes in main ui thread so you can add prepared marker to your map
        googleMap.addMarker(markerOptions[0]);
    }

    protected void onPostExecute(Void result) {
        // this also executes in main ui thread
    }
}

Note that DrawMarkersTask must be inner class of your Activity so it has direct access to UI. If you would like to make it separate class follow this: android asynctask sending callbacks to ui

Then you draw markers without blocking main thread like this:

DrawMarkersTask drawMarkersTask = new DrawMarkersTask();
drawMarkersTask.execute();

NOTE: This is just a trick. It has nothing to do with reducing or optimising complexity of this problem it just hides it from user by spreading operations in time. Yet still such approach is sometimes an acceptable compromise.

like image 70
Krzysiek Avatar answered Sep 21 '22 14:09

Krzysiek


Loading 11000 makers is a very heavy workload for the device. Even you can add all of them to the map, when you zoom out, you will probably face the same problem. There is a official Google article about various advanced marker management techniques. Use one of them to show only necessary markers instead of all of them.

like image 35
Joshua Avatar answered Sep 23 '22 14:09

Joshua