如何使用边界框限制管理谷歌地图中的1000多个自定义标记,以避免内存不足异常?

时间:2016-11-14 13:17:39

标签: android out-of-memory marker

我在我的项目中使用带有自定义标记的谷歌地图, 其中每个标记需要使用自定义视图进行设置,用于不同目的,例如具有折线和标记的路标以识别它们,带标记的多边形等。 现在,当这些标记超过1000时,位图无法加载到Map中,并且会抛出OOM。

我使用矢量drawables作为标记标识和普通文本视图来调平它们,创建位图拍摄180 * 210图像,

如何在没有滞后和OOM问题的情况下有效地管理它?

这是代码: 这是从 allGlobalPoints 数组中读取位置并区分它们并绘制它们。

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

用于创建标记 和位图使用的函数如下: - &gt; memoryCacheData 用作lrucache列表,用于快速访问位图

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

}

请帮助我如何管理位图而不冻结应用程序并避免内存不足异常,以及如何使用自定义视图管理那么多标记。

2 个答案:

答案 0 :(得分:2)

我知道回答这个问题为时已晚,但你可以使用 ClusterManager 来有效地显示1000个标记。首先将所有 lat long 放在ArrayList中,然后使用mClusterManager.addItems(ArrayList&lt; ..&gt;)立即将列表添加到 ClusterManager ;);,mClusterManager.cluster();.

这样做可以消除UI冻结问题和内存不足问题。

为了实现ClusterManager,请参考以下链接:https://github.com/googlemaps/android-maps-utils/blob/master/demo/src/com/google/maps/android/utils/demo/CustomMarkerClusteringDemoActivity.java

答案 1 :(得分:1)

一次添加超过1000个标记不是一个好习惯。另一种方法是创建所有标记的数组,并动态跟踪/显示最近的标记。可在此处找到类似的问题/回复:google maps api find nearest markers