我在我的项目中使用带有自定义标记的谷歌地图, 其中每个标记需要使用自定义视图进行设置,用于不同目的,例如具有折线和标记的路标以识别它们,带标记的多边形等。 现在,当这些标记超过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();
}
}
请帮助我如何管理位图而不冻结应用程序并避免内存不足异常,以及如何使用自定义视图管理那么多标记。
答案 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