Android加载多个标记阻止我的UI

Mad*_*dhu 3 android google-maps-markers

我在markerarray列表中大约有11000个标记,当我尝试在地图中加载时,即使我使用Thread和RunOnUi线程,它也会阻塞我的UI,还有其他更好的方法可以尝试吗?

 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();
Run Code Online (Sandbox Code Playgroud)

添加标记是我在地图中添加标记的方法

请提出更好的实施方式,谢谢

Krz*_*iek 5

在您提到的标记数量如此之大(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
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,DrawMarkersTask必须是Activity的内部类,因此它可以直接访问UI。如果您想将其设为单独的类,请执行以下操作:android asynctask将回调发送到ui

然后,您可以在不阻塞主线程的情况下绘制标记,如下所示:

DrawMarkersTask drawMarkersTask = new DrawMarkersTask();
drawMarkersTask.execute();
Run Code Online (Sandbox Code Playgroud)

注意:这只是一个把戏。它与减少或优化此问题的复杂性无关,只是通过及时分散操作将其隐藏在用户面前。但是,这种方法有时还是可以接受的折衷方案。


Jos*_*hua 2

加载11000个创客对于设备来说是一个非常繁重的工作量。即使您可以将它们全部添加到地图中,当您缩小时,您可能会遇到同样的问题。有一篇关于各种高级标记管理技术的Google 官方文章。使用其中之一仅显示必要的标记,而不是全部。