Bagaimana cara mengelola lebih dari 1000 penanda khusus di peta Google dengan batasan kotak pembatas untuk menghindari pengecualian kehabisan memori?

Saya menggunakan peta Google dengan penanda khusus di proyek saya, di mana setiap penanda perlu disetel dengan tampilan khusus, untuk tujuan berbeda seperti titik jalan dengan polyline dan penanda untuk mengidentifikasinya, poligon dengan penanda, dll. Sekarang ketika penanda ini lebih dari 1000, maka bitmap gagal dimuat ke dalam Peta dan OOM terlempar.

Saya telah menggunakan sumber daya dapat digambar untuk vektor sebagai identitas penanda dan tampilan teks normal untuk meratakannya, membuat bitmap membutuhkan gambar 180*210,

Bagaimana saya bisa mengelolanya secara efisien tanpa masalah lagging dan OOM?

ini kodenya: Ini untuk membaca lokasi dari Array allGlobalPoints dan membedakannya serta memplotnya.

mMap.clear();
    allpointPlotterThreadRunning = true;
    switchTospecific = true;
    final String POINTS = "points";
    final String POIS = "pois";
    final String FAILSAFE = "failsafe";
    final String POLYGON = "polygon";
    final String LASTPOLYGON = "lastpolygon";

    allMapPointPlotter = new AsyncTask<Void, Object, Void>() {
        ProgressDialog pgbarLoading;
        PolylineOptions polyline;
        PolygonOptions plogon;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            final View tiltleView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.progress_dialog_title_background, null);
            OpenSansRegularTextView tiltle = (OpenSansRegularTextView) tiltleView.findViewById(R.id.title_text);
            tiltle.setText("UAV Editor");

            pgbarLoading = new ProgressDialog(getActivity());
            pgbarLoading.setCancelable(false);
            pgbarLoading.setMessage("" + getActivity().getString(R.string.please_wait));
            pgbarLoading.setCustomTitle(tiltleView);
            pgbarLoading.show();
            markerPlottedList = new ArrayList<>();
            markerOnQueue = new ArrayList<>();

            ((DashboardActivity) getActivity()).setZoomOut();
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
            allpointPlotterThreadRunning = false;
        }


        @Override
        protected Void doInBackground(Void... voids) {
            try {
                if (allpointPlotterThreadRunning) {
                    if (allGlobalPoints.size() > 0) {


                        for (int global = 0; global < allGlobalPoints.size(); global++) {
                            if (allpointPlotterThreadRunning) {
                                //getting first object containing all points data
                                AllGlobalPointsArrayData globalDataObject = allGlobalPoints.get(global);  //This is the object of the position that contains all 5 data

                                if (globalDataObject.getPointsDataArray() != null && globalDataObject.getPointsDataArray().size() > 0) {

                                    ArrayList<RoutePointCoordinatesDataType> innerarraylist = globalDataObject.getPointsDataArray();

                                    for (int i = 0; i < innerarraylist.size(); i++) {
                                        if (allpointPlotterThreadRunning) {

                                            if (i == (innerarraylist.size() - 1)) {
                                                publishProgress(
                                                        POINTS,
                                                        Double.parseDouble(innerarraylist.get(i).getCoordinatesLatitude()),
                                                        Double.parseDouble(innerarraylist.get(i).getCoordinatesLongitude()),
                                                        i,
                                                        "" + innerarraylist.get(i).getTag(),
                                                        innerarraylist.get(i).getHeadingAngle(),
                                                        true
                                                );
                                            } else {
                                                publishProgress(
                                                        POINTS,
                                                        Double.parseDouble(innerarraylist.get(i).getCoordinatesLatitude()),
                                                        Double.parseDouble(innerarraylist.get(i).getCoordinatesLongitude()),
                                                        i,
                                                        "" + innerarraylist.get(i).getTag(),
                                                        innerarraylist.get(i).getHeadingAngle(),
                                                        false
                                                );
                                            }

                                        } else {
                                            break;
                                        }


                                    }
                                }
                                if (globalDataObject.getPoiDataArray() != null && globalDataObject.getPoiDataArray().size() > 0) {
                                    ArrayList<RoutePointCoordinatesDataType> innerList = globalDataObject.getPoiDataArray();

                                    if (innerList != null && innerList.size() > 0) {

                                        for (int i = 0; i < innerList.size(); i++) {
                                            if (allpointPlotterThreadRunning) {

                                                publishProgress(
                                                        POIS,
                                                        Double.parseDouble(innerList.get(i).getCoordinatesLatitude()),
                                                        Double.parseDouble(innerList.get(i).getCoordinatesLongitude()),
                                                        i,
                                                        "" + innerList.get(i).getTag()
                                                );

                                            } else {
                                                break;
                                            }

                                        }
                                    }
                                }

                                if (globalDataObject.getFailsafeDataArray() != null && globalDataObject.getFailsafeDataArray().size() > 0) {

                                    ArrayList<RoutePointCoordinatesDataType> innerArray = globalDataObject.getFailsafeDataArray();
                                    if (innerArray != null && innerArray.size() > 0) {
                                        for (int i = 0; i < innerArray.size(); i++) {
                                            if (allpointPlotterThreadRunning) {

                                                publishProgress(
                                                        FAILSAFE,
                                                        Double.parseDouble(innerArray.get(i).getCoordinatesLatitude()),
                                                        Double.parseDouble(innerArray.get(i).getCoordinatesLongitude()),
                                                        i,
                                                        "" + innerArray.get(i).getTag()
                                                );

                                            } else {
                                                break;
                                            }

                                        }
                                    }
                                }

                                if (globalDataObject.getPolygonLastUsedDataArray() != null && globalDataObject.getPolygonLastUsedDataArray().size() > 0) {
                                    ArrayList<RoutePointCoordinatesDataType> innerArray = globalDataObject.getPolygonLastUsedDataArray();
                                    if (innerArray != null && innerArray.size() > 0) {

                                        for (int i = 0; i < innerArray.size(); i++) {
                                            if (allpointPlotterThreadRunning) {


                                                if (i == (innerArray.size() - 1)) {
                                                    publishProgress(
                                                            LASTPOLYGON,
                                                            Double.parseDouble(innerArray.get(i).getCoordinatesLatitude()),
                                                            Double.parseDouble(innerArray.get(i).getCoordinatesLongitude()),
                                                            i,
                                                            "" + innerArray.get(i).getTag(),
                                                            true
                                                    );
                                                } else {
                                                    publishProgress(
                                                            LASTPOLYGON,
                                                            Double.parseDouble(innerArray.get(i).getCoordinatesLatitude()),
                                                            Double.parseDouble(innerArray.get(i).getCoordinatesLongitude()),
                                                            i,
                                                            "" + innerArray.get(i).getTag(),
                                                            false
                                                    );
                                                }

                                            } else {
                                                break;
                                            }


                                        }
                                    }
                                }

                                if (globalDataObject.getPolygonLastUsedDataArray() == null || globalDataObject.getPolygonLastUsedDataArray().size() == 0) {
                                    ArrayList<RoutePointCoordinatesDataType> innerArray = globalDataObject.getPolygonDataArray();
                                    if (innerArray != null && innerArray.size() > 0) {

                                        for (int i = 0; i < innerArray.size(); i++) {
                                            if (allpointPlotterThreadRunning) {


                                                if (i == (innerArray.size() - 1)) {
                                                    publishProgress(
                                                            POLYGON,
                                                            Double.parseDouble(innerArray.get(i).getCoordinatesLatitude()),
                                                            Double.parseDouble(innerArray.get(i).getCoordinatesLongitude()),
                                                            i,
                                                            "" + innerArray.get(i).getTag(),
                                                            true
                                                    );
                                                } else {
                                                    publishProgress(
                                                            POLYGON,
                                                            Double.parseDouble(innerArray.get(i).getCoordinatesLatitude()),
                                                            Double.parseDouble(innerArray.get(i).getCoordinatesLongitude()),
                                                            i,
                                                            "" + innerArray.get(i).getTag(),
                                                            false
                                                    );
                                                }

                                            } else {
                                                break;
                                            }

                                        }

                                    }
                                }
                            } else {
                                break;
                            }
                        }

                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Object... values) {
            super.onProgressUpdate(values);
            if (allpointPlotterThreadRunning) {
                String tagmarker = (String) values[0];
                int innerCounter = (Integer) values[3];

                if (tagmarker.equalsIgnoreCase(POINTS)) {
                    if (innerCounter == 0) {
                        polyline = new PolylineOptions();
                        polyline.width(4);
                        polyline.color(Color.parseColor("#425fa9"));
                        polyline.geodesic(true);
                    }

                    polyline.add(
                            new LatLng(
                                    (Double) values[1],
                                    (Double) values[2]
                            )
                    );
                    if ((Double) values[5] != 400) {
                        createMarker(
                                mMap,
                                (Double) values[1],
                                (Double) values[2],
                                innerCounter,
                                (String) values[4],
                                (Double) values[5]

                        );


                    } else {
                        createMarker(
                                mMap,
                                (Double) values[1],
                                (Double) values[2],
                                innerCounter,
                                (String) values[4],
                                400
                        );
                    }


                    if ((Boolean) values[6]) {
                        mMap.addPolyline(polyline);
                    }

                } else if (tagmarker.equalsIgnoreCase(POIS)) {

                    createMarkerPoi(
                            mMap,
                            (Double) values[1],
                            (Double) values[2],
                            innerCounter,
                            (String) values[4]
                    );


                } else if (tagmarker.equalsIgnoreCase(FAILSAFE)) {

                    createMarkerFailsafe(
                            mMap,
                            (Double) values[1],
                            (Double) values[2],
                            innerCounter,
                            (String) values[4]
                    );

                } else if (tagmarker.equalsIgnoreCase(POLYGON)) {
                    if (innerCounter == 0) {
                        plogon = new PolygonOptions();
                        plogon.fillColor(Color.parseColor("#20ff1a1a"));

                        plogon.strokeWidth((float) 5.1)
                                .strokeColor(Color.parseColor("#30ff1a1a"));
                    }
                    createMarkerPolygon(
                            mMap,
                            (Double) values[1],
                            (Double) values[2],
                            innerCounter,
                            (String) values[4]
                    );

                    plogon.add(new LatLng(
                            (Double) values[1],
                            (Double) values[2]
                    ));
                    if ((Boolean) values[5]) {
                        mMap.addPolygon(plogon);
                    }

                } else if (tagmarker.equalsIgnoreCase(LASTPOLYGON)) {
                    if (innerCounter == 0) {
                        plogon = new PolygonOptions();
                        plogon.fillColor(Color.parseColor("#20ff1a1a"));

                        plogon.strokeWidth((float) 5.1)
                                .strokeColor(Color.parseColor("#30ff1a1a"));
                    }

                    createMarkerPolygon(
                            mMap,
                            (Double) values[1],
                            (Double) values[2],
                            innerCounter,
                            (String) values[4]
                    );

                    plogon.add(new LatLng(
                            (Double) values[1],
                            (Double) values[2]
                    ));
                    if ((Boolean) values[5]) {
                        mMap.addPolygon(plogon);
                    }
                }
            }

        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            pgbarLoading.dismiss();
            allpointPlotterThreadRunning = false;

        }
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

Untuk membuat marker dan bitmap, fungsi berikut digunakan:-> memoryCacheData digunakan sebagai daftar lrucache untuk akses cepat ke bitmap

    protected void createMarker(GoogleMap map, double latitude, double longitude, int inner, String outer, double angle) {
    try {
        Bitmap resultantBitmap = null;
        if (((DashboardActivity) getActivity()).memoryCacheData != null && ((DashboardActivity) getActivity()).memoryCacheData.size() > 0) {
            resultantBitmap = ((DashboardActivity) getActivity()).memoryCacheData.get(latitude + "/" + longitude + "-OwnTab-" + inner + "|" + outer);
            if (resultantBitmap == null) {
                resultantBitmap = getMarkerBitmapFromView("P" + (inner + 1), "P", angle);
                ((DashboardActivity) getActivity()).memoryCacheData.put(latitude + "/" + longitude + "-OwnTabMarker-" + inner + "|" + outer, resultantBitmap);
            }
        } else {
            resultantBitmap = getMarkerBitmapFromView("P" + (inner + 1), "P", angle);
            ((DashboardActivity) getActivity()).memoryCacheData.put(latitude + "/" + longitude + "-OwnTabMarker-" + inner + "|" + outer, resultantBitmap);
        }

        map.addMarker(new MarkerOptions()
                .position(new LatLng(latitude, longitude))
                .anchor(0.5f, 0.5f)
                .title("" + outer)
                .icon(BitmapDescriptorFactory.fromBitmap(resultantBitmap))
        );


    } catch (Exception e) {
        e.printStackTrace();
    }

}

Tolong bantu saya cara mengelola bitmap tanpa membekukan aplikasi dan menghindari pengecualian kehabisan memori, dan bagaimana saya bisa mengelola penanda sebanyak itu dengan tampilan khusus.


person bodhidipta    schedule 14.11.2016    source sumber
comment
Tidak mungkin... 180*210*4*1000 = 151 MB hanya untuk bitmap Anda...   -  person Selvin    schedule 14.11.2016
comment
Jika saya menggunakan kanvas untuk menggambar penanda alih-alih membuat bitmap dari cache XML, apakah ini membantu mengurangi ukuran bitmap?   -  person bodhidipta    schedule 16.11.2016


Jawaban (2)


Saya tahu sudah terlambat untuk menjawabnya, tetapi Anda dapat menggunakan ClusterManager untuk menampilkan 1000 penanda secara efisien. Pertama-tama letakkan semua lat long di ArrayList dan kemudian tambahkan daftar ke ClusterManager sekaligus dengan menggunakan mClusterManager.addItems(ArrayList‹..> );, mClusterManager.cluster();.

Melakukan hal ini akan menghilangkan masalah pembekuan UI dan masalah kehabisan memori.

Untuk mengimplementasikan ClusterManager silakan lihat tautan ini: https://github.com/googlemaps/android-maps-utils/blob/master/demo/src/com/google/maps/android/utils/demo/CustomMarkerClusteringDemoActivity.java

person Idris Bohra    schedule 04.07.2017

Menambahkan lebih dari 1000 penanda sekaligus bukanlah praktik yang baik. Alternatifnya adalah dengan membuat larik semua penanda Anda dan melacak/menampilkan penanda terdekat secara dinamis. Pertanyaan/tanggapan serupa dapat ditemukan di sini: google Maps api menemukan penanda terdekat

person Jenever    schedule 14.11.2016