如何在不锁定UI线程的情况下快速向Google Map API v2中的MapFragment添加许多标记?

时间:2015-05-20 17:27:32

标签: android google-maps google-maps-markers google-maps-api-2 supportmapfragment

我正在使用Google Map API v2并在MapFragment中的地图上显示标记。

我需要快速向地图添加许多标记,但不要锁定UI线程。我尝试了两种方法,但要么在绘制所有标记时需要很长时间才能添加大量标记或UI线程冻结。有没有不同的方法来做得更好?

方法#1(快速添加它们,但锁定UI线程直到它们都被添加):

public void addMarkersFast(List<MarkerThing> thingsToShow) {
    if (getMap() == null) return; // Will be null for any device without google play services installed

    for (MarkerThing thing : thingsToShow) {
        getMap().addMarker(createMarker(thing));
    }
}

方法#2(立即开始显示,但可能需要20-30秒才能添加所有标记):

public void addMarkersSlow(final MarkerThingArray thingsToShow) {
    if (getMap() == null) return; // Will be null for any device without google play services installed

    MarkerThing thing = thingsToShow.get(i);
    getMap().addMarker(createMarker(thing));
    (new Handler()).postDelayed(new Runnable() {    // give some time for main thread to draw
        @Override
        public void run() {
            addMarkersSlow(thingsToShow, i + 1);
        }
    }, 1);
}

如何以不同的方式显示2k +标记场景中的所有标记,而不像方法#1那样锁定UI线程3-4秒,而不需要花费30秒逐步添加它们,就像方法#2一样?

2 个答案:

答案 0 :(得分:2)

单个可见地图区域上的2k +标记是要管理和绘制的许多子视图和对象,更不用说一些潜在的可用性问题了。

检查标记聚类:

https://developers.google.com/maps/documentation/android/utility/marker-clustering

这允许你&#34;集群&#34;附近的标记成一个折叠标记。您应该尝试将标记/子视图的总数减少到几十个。无论如何,这样的技术应该会有所帮助。

答案 1 :(得分:1)

我认为您可以编写AsynTask并在onProgress中发布标记。我不是使用AsyncTasks的忠实粉丝,所以我会使用RxJava(使用RxAndroid用于Android特定的调度程序)。

示例:

Observable.just(thingsToShow)
    .subscribeOn(Schedulers.newThread())
    .map(new Func1<MarkerThing, Marker>() {
        @Override
        public Marker call(MarkerThing thing) {
            return createMarker(thing);
        }
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Subscriber<Marker>() {
        @Override
        public void onNext(Marker marker) {
            getMap().addMarker(marker);
        }

        @Override
        public void onCompleted() {
        }

        @Override
        public void onError(Throwable e) { }
    });