android 加载多个标记阻止我的 UI
android load multiple markers block my UI
我在 markerarray 列表中有大约 11000 个标记,当我尝试加载地图时它会阻止我的 UI,即使我使用 Thread 和 RunOnUi 线程,还有其他更好的方法我可以尝试吗?
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();
添加标记是我在地图中添加标记的方法
请提出更好的实现方式
提前致谢
加载11000个maker对设备来说是一个非常繁重的工作量。即使您可以将它们全部添加到地图中,当您缩小地图时,您也可能会面临同样的问题。
关于各种高级标记管理技术,有一个 official Google article。使用其中之一来仅显示必要的标记而不是所有标记。
对于您提到的标记数量 (11000),强烈建议使用标记聚类。您可以在以下位置阅读更多相关信息:https://developers.google.com/maps/documentation/android-api/utility/marker-clustering
如果您仍然想在没有标记聚类的情况下执行此操作,可以使用一个简单的技巧来改善用户体验。
由于添加标记会修改 UI - 它必须在主 UI 线程中完成。一次添加太多标记会阻塞主线程,因此应用程序在忙于添加标记时不会响应任何用户操作。最终用户可能会觉得应用程序已挂起或停止,甚至可能导致 ANR
诀窍是逐渐添加标记,为主线程留出一些中断来处理其他操作,以便应用程序始终保持响应。
我会建议这样的方法:
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
}
}
请注意,DrawMarkersTask 必须位于 Activity 的内部 class,因此它可以直接访问 UI。如果您想将其分开 class,请按照以下步骤操作:android asynctask sending callbacks to ui
然后像这样在不阻塞主线程的情况下绘制标记:
DrawMarkersTask drawMarkersTask = new DrawMarkersTask();
drawMarkersTask.execute();
注意:这只是一个技巧。它与降低或优化此问题的复杂性无关,它只是通过及时分散操作来向用户隐藏它。然而,这种方法有时仍然是一种可以接受的妥协。
我在 markerarray 列表中有大约 11000 个标记,当我尝试加载地图时它会阻止我的 UI,即使我使用 Thread 和 RunOnUi 线程,还有其他更好的方法我可以尝试吗?
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();
添加标记是我在地图中添加标记的方法
请提出更好的实现方式 提前致谢
加载11000个maker对设备来说是一个非常繁重的工作量。即使您可以将它们全部添加到地图中,当您缩小地图时,您也可能会面临同样的问题。 关于各种高级标记管理技术,有一个 official Google article。使用其中之一来仅显示必要的标记而不是所有标记。
对于您提到的标记数量 (11000),强烈建议使用标记聚类。您可以在以下位置阅读更多相关信息:https://developers.google.com/maps/documentation/android-api/utility/marker-clustering
如果您仍然想在没有标记聚类的情况下执行此操作,可以使用一个简单的技巧来改善用户体验。
由于添加标记会修改 UI - 它必须在主 UI 线程中完成。一次添加太多标记会阻塞主线程,因此应用程序在忙于添加标记时不会响应任何用户操作。最终用户可能会觉得应用程序已挂起或停止,甚至可能导致 ANR
诀窍是逐渐添加标记,为主线程留出一些中断来处理其他操作,以便应用程序始终保持响应。
我会建议这样的方法:
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
}
}
请注意,DrawMarkersTask 必须位于 Activity 的内部 class,因此它可以直接访问 UI。如果您想将其分开 class,请按照以下步骤操作:android asynctask sending callbacks to ui
然后像这样在不阻塞主线程的情况下绘制标记:
DrawMarkersTask drawMarkersTask = new DrawMarkersTask();
drawMarkersTask.execute();
注意:这只是一个技巧。它与降低或优化此问题的复杂性无关,它只是通过及时分散操作来向用户隐藏它。然而,这种方法有时仍然是一种可以接受的妥协。