2017-08-06 177 views
2

我目前正在嘗試編寫一個應用程序,使用標記在地圖上顯示幾個位置。即使只使用一個相對較小的標記集(我已經看到了StackOverflow問題,人們想要繪製超過100k的問題),但我的表現非常糟糕,我的地圖需要幾秒鐘才能移動。谷歌地圖Android API性能極差

我也有我的GPU性能分析的截圖,我想知道,如果任何人都可以理解爲什麼這些電話都是如此極高:

Screenshot of GPU profiling on-screen

我試圖剖析使用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

對不起,最近的答案,你可能已經找到了解決方案,但它可能會幫助其他人。

您考慮過Clusters嗎?

您遇到的問題是,它需要大量資源才能在地圖上渲染所有這些標記,並且每次您的視圖移動時都會重新渲染api。

當許多引腳真的很接近時,你不能真正區分它們。默認情況下,羣集將根據地圖上的縮放對它們進行分組,以優化渲染和可視化。 如果默認行爲或外觀不符合您的口味,您可以輕鬆覆蓋它。

希望我幫了忙。