我目前正在尝试使用标记编写一个在地图上显示多个位置的应用。即使只与相对较小的小型人合作也是如此。一套标记(我已经看到StackOverflow问题,人们想要绘制超过100k),我的表现很差,我的地图需要几秒钟才能移动。
我还有我的GPU分析的截图,我想知道是否有人能理解为什么这些呼叫如此极高:
我曾试图使用DDMS来分析我的应用程序,但这似乎并没有给我任何确凿的答案。
我使用的代码如下:
tab_map.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.google.android.gms.maps.SupportMapFragment"
class="com.google.android.gms.maps.SupportMapFragment"
android:id="@+id/city_map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize" />
</FrameLayout>
LocationFragment.java
/* a whole list of imports and package definition */
/**
* Created by Ruben on 05-08-17.
*/
public class LocationsFragment extends Fragment
implements OnMapReadyCallback {
private static final String TAG = LocationsFragment.class.getSimpleName();
private LocationsFragment instance;
private City city;
private List<Marker> markers;
private List<Location> locations;
private Target iconTarget;
private GoogleMap map;
private SupportMapFragment mapFragment;
private BitmapDescriptor markerIcon;
private Bitmap markerIconBitmap;
private ApiService apiService;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.tab_map, null);
}
@Override
public void onActivityCreated(Bundle savedInstanceStace) {
super.onActivityCreated(savedInstanceStace);
// Set up the view
instance = this;
mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.city_map);
apiService = RestClient.getClient(getContext()).create(ApiService.class);
city = getArguments().getParcelable("city");
markers = new ArrayList<>();
iconTarget = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
markerIconBitmap = bitmap;
updateMarkerIcons();
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
// Start async processes
// Load Google map
mapFragment.getMapAsync(this);
// Load locations from API
getLocations();
// Load custom marker for city
getCityMarker();
}
private void getCityMarker() {
Picasso
.with(getContext())
.load(city.getMarker().getUrl())
.resize(ScreenUtils.convertDIPToPixels(getContext(), 24), ScreenUtils.convertDIPToPixels(getContext(), 24))
.into(iconTarget);
}
@Override
public void onMapReady(GoogleMap map) {
this.map = map;
if(markerIconBitmap == null) {
markerIcon = BitmapDescriptorFactory.fromAsset("default1.png");
}else{
markerIcon = BitmapDescriptorFactory.fromBitmap(markerIconBitmap);
}
if (ContextCompat.checkSelfPermission(this.getContext(), "ACCESS_FINE_LOCATION") == PackageManager.PERMISSION_GRANTED) {
map.setMyLocationEnabled(true);
} else {
Toast.makeText(instance.getContext(), getString(R.string.no_location_permission), Toast.LENGTH_LONG).show();
}
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(city.getCenter().getLat(), city.getCenter().getLong()), 12));
setMarkers();
}
public void getLocations() {
Call<LocationsResponse> call = apiService.getLocations(city.getId());
call.enqueue(new Callback<LocationsResponse>() {
@Override
public void onResponse(Call<LocationsResponse> call, Response<LocationsResponse> response) {
if(response.code() != 200) {
Toast.makeText(instance.getContext(), getString(R.string.retrieving_locations) + "1", Toast.LENGTH_LONG).show();
return;
}
Log.d(TAG, "Received locations: " + response.body().getLocations().size());
locations = response.body().getLocations();
setMarkers();
}
@Override
public void onFailure(Call<LocationsResponse> call, Throwable t) {
t.printStackTrace();
Toast.makeText(instance.getContext(), getString(R.string.retrieving_locations) + "1", Toast.LENGTH_LONG).show();
}
});
}
public void setMarkers() {
Log.d(TAG, "Calling setMarkers");
if(map != null && locations != null) {
// Remove all the old markers
if(!markers.isEmpty()) {
int numMarkers = markers.size();
for(int i = 0; i < numMarkers; i++) {
markers.get(i).remove();
}
markers.clear();
}
// Create a new marker for each location
int numLocations = locations.size();
Log.d(TAG, "Setting markers for " + numLocations + " locations");
for(int i = 0; i < numLocations; i++) {
Location location = locations.get(i);
markers.add(map.addMarker(
new MarkerOptions()
.position(new LatLng(location.getPosition().getLat(), location.getPosition().getLong()))
//.icon(markerIcon)
//.title(location.getName())
//.snippet(getString(R.string.location_marker_text, NumberFormat.getInstance().format(location.getStones())))
));
}
}
}
public void updateMarkerIcons() {
Log.d(TAG, "Calling updateMarkerIcons");
if(map != null && markerIconBitmap != null) {
markerIcon = BitmapDescriptorFactory.fromBitmap(markerIconBitmap);
}
if(map != null && !markers.isEmpty()) {
int numMarkers = markers.size();
for(int i = 0; i < numMarkers; i++) {
Marker marker = markers.get(i);
//marker.setIcon(markerIcon);
}
}
}
@Override
public void onDestroyView() {
Picasso.with(this.getContext()).cancelRequest(iconTarget);
mapFragment.onDestroyView();
super.onDestroyView();
}
public void updateLocations() {
if(locations != null) {
getLocations();
}
}
public void setCity(City city) {
this.city = city;
getCityMarker();
}
}
正如您所看到的,我取消注释了我为标记设置.snippet
或.icon
的一些行,因为我怀疑这可能是问题所在。可悲的是,这似乎不是问题所在。
使用断点,我试图确认我设置/编辑标记的所有函数都没有被调用,我发现这绝对不是这种情况。设置标记后,此文件中不会执行其他代码。我的所有其他活动似乎运行正常,所以我开始相信这是与Google地图相关的问题。值得注意的是,当我离开标记时,意味着不再出现在我的屏幕边界,性能不错,滚动看起来很流畅。
答案 0 :(得分:1)
对于迟到的回答,很抱歉,您可能已经找到了解决方案,但它可能对其他人有帮助。
您考虑过Clusters吗?
您遇到的问题是,需要大量资源才能在地图上渲染所有这些标记,并且每次视图移动时都会重新渲染api。
当许多引脚真正靠近时,你无法真正区分它们。默认情况下,群集将根据地图上的缩放对它们进行分组,以优化渲染和可视化。 如果默认行为或外观不符合您的喜好,您可以轻松覆盖它。
希望我帮助过。