【问题标题】:MapFragment return nullMapFragment 返回 null
【发布时间】:2013-10-01 05:46:43
【问题描述】:
mMapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentByTag(MAP_FRAGMENT_TAG);

        // We only create a fragment if it doesn't already exist.
        if (mMapFragment == null) {
          mMapFragment = SupportMapFragment.newInstance();


            // Then we add it using a FragmentTransaction.
            FragmentTransaction fragmentTransaction =
                    getSupportFragmentManager().beginTransaction();
            fragmentTransaction.add(MapLay.getId(), mMapFragment, MAP_FRAGMENT_TAG);
             fragmentTransaction.commit();


            mMap=mMapFragment.getMap();

通过此代码地图可见但无法访问地图

mMap=mMapFragment.getMap();显示空值错误如何解决这个问题

【问题讨论】:

  • 应该是mMap=mMapFragment.getMap()
  • 对不起先生,这里输入错误,但我写的代码是正确的
  • @RanaRaman 我有个忙,只是想分析一下。你能扩展SupportMapFragment吗?将Log 放入onCreate()。在mMap=mMapFragment.getMap() 之前添加一个日志。让我知道要先调用的Log

标签: android google-maps


【解决方案1】:

更新 1: getMap()弃用

最好使用MapFragment/SupportMapFragmentgetMapAsync()方法。示例如何使用如下所示的方法(复制自他们的documentation)。

import com.google.android.gms.maps.*;
import com.google.android.gms.maps.model.*;
import android.app.Activity;
import android.os.Bundle;

public class MapPane extends Activity implements OnMapReadyCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.map_activity);

        MapFragment mapFragment = (MapFragment) getFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap map) {
        LatLng sydney = new LatLng(-33.867, 151.206);

        map.setMyLocationEnabled(true);
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 13));

        map.addMarker(new MarkerOptions()
                .title("Sydney")
                .snippet("The most populous city in Australia.")
                .position(sydney));
    }

}

引用 Google 的 MapFragment/SupportMapFragment

GoogleMap 只能在底层使用 getMap() 获取 地图系统已加载并且片段中的底层视图存在。 该类自动初始化地图系统和视图; 但是你不能保证它什么时候准备好,因为这 取决于 Google Play 服务 APK 的可用性。如果一个 GoogleMap 不可用,getMap() 将返回 null。

在您的代码上,您在提交MapFragment 之后立即检索GoogleMap。等到MapFragment 完全加载到活动中,这样您就可以获得GoogleMap

也许,您可以使用接口将GoogleMapMapFragment 传递到Activity,如下所示。

public class MyMapFragment extends SupportMapFragment
{
  private MapCallback callback;

  public void setMapCallback(MapCallback callback)
  {
    this.callback = callback;
  }

  public static interface MapCallback
  {
     public void onMapReady(GoogleMap map);
  }

  @Override public void onActivityCreated(Bundle savedInstanceState)
  {
     super.onActivityCreated(savedInstanceState);
     if(callback != null) callback.onMapReady(getMap());     
  }
}


public class MyActivity extends Activity implements MyMapFragment.MapCallback
{
   // .........
  @Override
  public void onCreate(Bundle onsavedInstanceState)
  {
        mMapFragment = (MyMapFragment) getSupportFragmentManager()
                .findFragmentByTag(MAP_FRAGMENT_TAG);

        // We only create a fragment if it doesn't already exist.
        if (mMapFragment == null) {
               mMapFragment = MyMapFragment.newInstance();

               mMapFragment.setMapCallback(this); // This activity will receive the Map object once the map fragment is fully loaded

               // Then we add it using a FragmentTransaction.
               FragmentTransaction fragmentTransaction =
                    getSupportFragmentManager().beginTransaction();
               fragmentTransaction.add(MapLay.getId(), mMapFragment, MAP_FRAGMENT_TAG);
               fragmentTransaction.commit();

         }
         else
         {
               mMapFragment.setMapCallback(this); // This activity will receive the Map object once the map fragment is fully loaded
         }

  @Override
  public void onMapReady(GoogleMap map)
  {
     // Do what you want to map
  }

}

【讨论】:

  • 如果我做了onCreate方法,setContentView(R.layout.activity_map);在布局中有一个将被加载的片段?是这样吗
  • mMapFragment = MyMapFragment.newInstance(); - 必需的 MyMapFragment(),找到 SupportMapFragment()。我也无法将新实例转换为 MyMapFragment,有人知道为什么吗?
  • @DanielWilson 您需要将您的MyMapFragment 扩展到SupportMapFragment
  • 是的,代码无法编译,因为 newInstance() 返回了一个新的 SupportMapFragment 实例,并且只有在您尝试强制转换时才会抛出 ClassCastException。你需要使用new MyMapFragment()
【解决方案2】:

导入部分

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;

在oncreate里面

SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map); 
    mMap = mapFragment.getMap();

还有 Xml 部分

<fragment 
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment" />

确保你已经投入

<meta-data android:name="com.google.android.maps.v2.API_KEY"
              android:value="api key"/> 

在您的 &lt;application&gt;&lt;/application&gt; 标签内。

并在清单文件中授予这些权限

<permission
          android:name="packagename.permission.MAPS_RECEIVE"
          android:protectionLevel="signature"/>
    <uses-permission android:name="packagename.permission.MAPS_RECEIVE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>    
    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true"/>

【讨论】:

    【解决方案3】:

    你的 xml 应该有 SupportMapFragment

    <fragment
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    

    【讨论】:

    • 先生,我没有在运行时使用 XML 创建片段
    【解决方案4】:

    当我输入这段代码时,我解决了这个问题:

    @Override
    public void onPause() {
    
        Fragment fragment = (getFragmentManager().findFragmentById(R.id.map_tab));  
        FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
        ft.remove(fragment);
        ft.commit();
        super.onPause();
    }
    

    或者我把这段代码放在 onCreate 中

    if (mView != null) {
         ViewGroup parent = (ViewGroup) mView.getParent();
         if (parent != null) {
             parent.removeView(mView);
         }
     }
     try {
      mView = inflater.inflate(R.layout.tab_map_layout, container, false);
     } catch (InflateException e) {
    
     }
    

    【讨论】:

      【解决方案5】:

      按照 2013 年 10 月 1 日 6:05 的 @Glenn-- 评论创建这段源代码。

      我的实现是用 MapFragment 替换 SupportMapFragment 并支持 Google 地图版本 2

      我想再次记住:

      只有在加载了底层地图系统并且片段中存在底层视图时,才能使用 getMap() 获取 GoogleMap。该类自动初始化地图系统和视图;但是,您无法保证它何时准​​备就绪,因为这取决于 Google Play 服务 APK 的可用性。如果 GoogleMap 不可用,getMap() 将返回 null。

      我的实现:

      AndroidManifest.xml

      <!-- Permissions -->
      
      <!-- Used by the Google Maps API to download map tiles from Google Maps servers. -->
      <uses-permission android:name="android.permission.INTERNET"></uses-permission>
      
      <!-- Allows the Google Maps API to check the connection status in order to determine whether data can be downloaded. -->
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
      
      <!-- Allows the Google Maps API to cache map tile data in the device's external storage area. -->
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
      
      <!-- Allows the Google Maps API to use WiFi or mobile cell data (or both) to determine the device's location. -->
      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
      
      <!-- Allows the Google Maps API to use the Global Positioning System (GPS) to determine the device's location to within a very small area. -->
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
      <!-- Permissions -->
      
      <!-- Required OpenGL ES 2.0. for Maps V2 -->
      <!-- 
          The Google Maps Android API uses OpenGL ES version 2 to render the map. 
          If OpenGL ES version 2 is not installed, your map will not appear. 
          sWe recommend that you add the following <uses-feature> element as a child of the <manifest> element in AndroidManifest.xml:
       -->
       <uses-feature
          android:glEsVersion="0x00020000"
          android:required="true"/>
      
      <application
          android:allowBackup="true"
          android:icon="@drawable/ic_launcher"
          android:label="@string/app_name"
          android:theme="@style/AppTheme" >
      
          <!-- Google Play Services -->
          <meta-data
              android:name="com.google.android.gms.version"
              android:value="@integer/google_play_services_version" />
      
          <!-- Goolge Maps API Key -->
          <meta-data
              android:name="com.google.android.maps.v2.API_KEY"
              android:value="AIzaSyATC4WBLLewjdwYDFVTnJH8hA18gG_GgvY" />
      
      </application>
      

      activity_main.xml

      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:paddingBottom="@dimen/activity_vertical_margin"
          android:paddingLeft="@dimen/activity_horizontal_margin"
          android:paddingRight="@dimen/activity_horizontal_margin"
          android:paddingTop="@dimen/activity_vertical_margin"
          tools:context="mapa.bg.MapaMainActivity" 
          android:background="#ccc">
      
          <!-- Google Map Container -->
          <RelativeLayout 
              android:id="@+id/google_map_container"
              android:layout_width="match_parent"
              android:layout_height="match_parent"/>
          <!-- Google Map Container -->
      </RelativeLayout>
      

      ApplicationMapFragment.java

      public class ApplicationMapFragment extends MapFragment {
      
          private MapCallback callback;
      
          public void setMapCallback(MapCallback callback) {
              this.callback = callback;
          }
      
          public static interface MapCallback {
              public void onMapReady(GoogleMap map);
          }
      
          @Override 
          public void onActivityCreated(Bundle savedInstanceState) {
              super.onActivityCreated(savedInstanceState);
              if(callback != null) callback.onMapReady(getMap()); 
          }
      
          /**
           * Initialize default Google Maps Options for our Application
           * @return GoogleMapOptions
           */
          public GoogleMapOptions initializeGoogleMapsOptions() {
              GoogleMapOptions googleMapOptions = new GoogleMapOptions()
                  .mapType(GoogleMap.MAP_TYPE_HYBRID);
      
              return googleMapOptions;
          }
      }
      

      MainActivity.java

      public class MainActivity extends Activity implements ApplicationMapFragment.MapCallback {
      
          // Get Class Name
          private static String TAG = MainActivity.class.getName();
      
          // Create a new Map fragment
          private ApplicationMapFragment mapFragment;
      
          // Google Map Fragment Name
          private static String MAP_FRAGMENT_TAG = "google_maps_fragment";
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              try {
                      initilizeMapFragment();
              } catch (Exception e) {
                      e.printStackTrace();
                      Log.e(TAG, "Google Maps can't be loaded", e);
              }
          }
      
          /**
           * Initialize a new Map Fragment
           */
          private void initilizeMapFragment() {
      
              // Try to get Map Fragment
              mapFragment = (ApplicationMapFragment) getFragmentManager()
                      .findFragmentByTag(MAP_FRAGMENT_TAG);
      
              // We only create a fragment if it doesn't already exist.
              if (mapFragment == null) {
                  mapFragment = new ApplicationMapFragment();
                  mapFragment.initializeGoogleMapsOptions();
      
                  // This activity will receive the Map object once the map fragment is fully loaded
                  mapFragment.setMapCallback(this);
      
                  // Then we add it using a FragmentTransaction.
                  FragmentTransaction fragmentTransaction =
                          getFragmentManager().beginTransaction();
                  fragmentTransaction.add(R.id.google_map_container, mapFragment, MAP_FRAGMENT_TAG);
                  fragmentTransaction.commit();
              } else {
                  // This activity will receive the Map object once the map fragment is fully loaded
                  mapFragment.setMapCallback(this);
              }
          }
      
          @Override
          public void onMapReady(GoogleMap map) {
              Log.d(TAG, "Google Map is loaded");
      
              MarkerOptions marker = new MarkerOptions()
                  .position(new LatLng(10, 10))
                  .title("Hello World");
      
              map.addMarker(marker);
          }
      }
      

      【讨论】:

        【解决方案6】:

        确实是 hackish 解决方案,但是因为片段 API 很差...

        请注意,我是从自定义视图执行此操作并使用 (Activity)getContext() 访问活动

                    addOnLayoutChangeListener(new OnLayoutChangeListener(){
                        @Override
                        public void onLayoutChange(View v, int left, int top,
                                int right, int bottom, int oldLeft, int oldTop,
                                int oldRight, int oldBottom) {
        
                            GoogleMap map = mapFragment.getMap();
        
                            if (map != null) {
                                 //Do stuff
                            }else{
                                 removeOnLayoutChangeListener(this);
                            }
                        }
                    });
        

        【讨论】:

        • 你能说得更具体一点吗?您的意思是一旦地图开始加载(意味着它将返回地图,而不是 null),就会调用 onLayoutChange?这是写在活动文件上的吗?
        • 您可以将布局更改侦听器添加到包含地图片段的视图中。
        • 是的,当地图完全加载时,似乎调用了侦听器。就我而言,我使用的是自定义视图并在 onAttachedToWindow 方法中添加了此代码,但也许您可以在 Activity 的 onCreate 中执行相同操作。
        猜你喜欢
        • 2014-09-30
        • 1970-01-01
        • 1970-01-01
        • 2014-12-22
        • 1970-01-01
        • 1970-01-01
        • 2020-06-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多