2015-06-22 28 views
20

我使用的是Google地圖服務的com.google.android.gms:play-services-maps:7.5.0版本。當試圖打電話給我時,我得到java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.SupportMapFragment.getMapAsync(com.google.android.gms.maps.OnMapReadyCallback)' on a null object referencemapFragment.getMapAsync(this) - NullPointerException

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    SupportMapFragment mapFragment = (SupportMapFragment) getActivity().getSupportFragmentManager() 
      .findFragmentById(R.id.map); 
    mapFragment.getMapAsync(this); //error 

    return inflater.inflate(R.layout.fragment_example_map, container, false); 
} 

fragment_example_map.xml文件:

<FrameLayout 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" 
    tools:context="app.ExampleMap"> 

    <fragment xmlns:android="http://schemas.android.com/apk/res/android" 
     android:name="com.google.android.gms.maps.SupportMapFragment" 
     android:id="@+id/map" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"/> 
</FrameLayout> 

回答

6

您正試圖找到一個片段存在之前。您指出具有該片段的佈局是fragment_example_map.xml。但是,您正在嘗試在膨脹該佈局文件之前查找地圖片段。這不起作用。

除此之外,您似乎試圖從另一個片段內的片段的onCreateView()方法中獲取映射片段。我不知道你爲什麼在這裏嵌入片段,因爲它看起來會讓你的代碼更復雜,更脆弱,沒有明顯的好處。

+0

凡將是一個合適的地方調用'getMapAsync()'呢?基本上我的應用程序有3個片段,1個活動和一個ViewPager在這些片段之間滑動。應該是活動的'onCreate()'? – Neutrino

+0

@Neutrino:「基本上我的應用程序有3個片段,1個活動和一個在這些片段之間滑動的ViewPager」 - 你不需要嵌套片段。你的活動有一個'ViewPager'。你的'PagerAdapter'創建三個片段。不需要嵌套。讓'FragmentPagerAdapter'直接創建'SupportMapFragment'的新實例;你不需要膨脹佈局。這個示例顯示了一個包含10個地圖片斷的'ViewPager':https://github.com/commonsguy/cw-omnibus/tree/master/MapsV2/Pager – CommonsWare

+0

對不起,我有點迷路。我的ViewPagerAdapter的getItem()在這種情況下檢查位置並調用'return new Example()' - 我猜在這種情況下需要膨脹佈局嗎?然後我不太確定我應該在哪裏做我的操作:在片段代碼,活動代碼或其他任何地方。 – Neutrino

89

我與片段地圖評論,首先你應該refrenece你的觀點,你會叫的東西從它,這就是爲什麼我吹我的看法首先getActivity().getSupportFragmentManager()


View view = inflater.inflate(R.layout.activity_maps, null, false);

二呼兒片段經理this.getChildFragmentManager()代替

這裏是完整的例子,以查看地圖

import android.os.Bundle; 
import android.support.annotation.Nullable; 
import android.support.v4.app.Fragment; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 

import com.google.android.gms.maps.CameraUpdateFactory; 
import com.google.android.gms.maps.GoogleMap; 
import com.google.android.gms.maps.OnMapReadyCallback; 
import com.google.android.gms.maps.SupportMapFragment; 
import com.google.android.gms.maps.model.LatLng; 
import com.google.android.gms.maps.model.MarkerOptions; 

public class ClinicFragment extends Fragment implements OnMapReadyCallback { 

    private GoogleMap mMap; 

    public static ClinicFragment newInstance() { 
     ClinicFragment fragment = new ClinicFragment(); 
     return fragment; 
    } 

    @Nullable 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.activity_maps, null, false); 

     SupportMapFragment mapFragment = (SupportMapFragment) this.getChildFragmentManager() 
       .findFragmentById(R.id.map); 
     mapFragment.getMapAsync(this); 

     return view; 
    } 


    /** 
    * Manipulates the map once available. 
    * This callback is triggered when the map is ready to be used. 
    * This is where we can add markers or lines, add listeners or move the camera. In this case, 
    * we just add a marker near Sydney, Australia. 
    * If Google Play services is not installed on the device, the user will be prompted to install 
    * it inside the SupportMapFragment. This method will only be triggered once the user has 
    * installed Google Play services and returned to the app. 
    */ 
    @Override 
    public void onMapReady(GoogleMap googleMap) { 
     mMap = googleMap; 

     // Add a marker in Sydney and move the camera 
     LatLng sydney = new LatLng(-34, 151); 
     mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney")); 
     mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)); 
    } 
} 

需要許可

<permission 
    android:name="your.package.name.permission.MAPS_RECEIVE" 
    android:protectionLevel="signature" /> 
<uses-permission android:name="your.package.name.permission.MAPS_RECEIVE"/> 

<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<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-feature 
    android:glEsVersion="0x00020000" 
    android:required="true"/> 

大多數進口谷歌地圖鍵

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

更新,如果你面對Error inflating class fragment

添加該元數據
<meta-data 
     android:name="com.google.android.geo.API_KEY" 
     android:value="your_key_here" /> 

夏日爲mainfest

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="your.package.name" > 
// permission here 

<application 
     android:name=".Activities.MyApplication" 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 

    // feature element 
    // maps key 

    </application> 

</manifest> 

activity_maps.xml

<fragment xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:map="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/map" 
    android:name="com.google.android.gms.maps.SupportMapFragment" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.imaadv.leaynik.ClinicFragment" /> 
+10

爲什麼這個答案不是最好的答案?非常感謝這個答案。 – partiz

+0

@Fawzy,我沒有看到'getChildFragmentManager' – Jeremiah

+1

只有這個解決方案爲我工作。謝謝 –

0

替換此代碼

<fragment 
    android:name="com.google.android.gms.maps.MapFragment" 
    android:id="@+id/map" 
    android:layout_width="fill_parent" 
    android:layout_height="400dp" /> 

if (googleMap == null) { 
     mapFrag = (MapFragment)getFragmentManager().findFragmentById(R.id.map); 
     mapFrag.getMapAsync(this); 
    }else{ 
     GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); 

    } 
+1

isGooglePlayServicesAvailable(this)is deprecated –

11

使用getChildFragmentManager()代替片段中的getActivity().getSupportFragmentManager()

像:

SupportMapFragment mapFragment = (SupportMapFragment)getChildFragmentManager() 
      .findFragmentById(R.id.map); 
    mapFragment.getMapAsync(this); 
2

根據Android版本或SDK版本5及以上使用getChildFragmentManager()和它下面使用getFragmentManager()。

+0

你有任何文件或鏈接?在我的例子中,getChildFragmentManager()爲所有Android版本返回一個有效的FragmentManager。但getFragmentManager對於Android 4及更低版本返回null。 –

+0

你能否提供文件?這大致上是我的問題的解決方案,但我無法將其投入生產,直到我確定了這些版本號。我讀的所有內容都是指API 17以上。 –

1

使用這個。

GoogleMap gooleMap; 

    ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMapAsync(new OnMapReadyCallback() { 
     @Override 
     public void onMapReady(GoogleMap map) { 
      googleMap = map; 
      } 
7

只需調用中onResumesupportMapFragment.getMapAsync(this);如果您在您的片段使用android:name="com.google.android.gms.maps.MapFragment"然後改變你的代碼:如果您在您的片段使用android:name="com.google.android.gms.maps.SupportMapFragment"

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

然而然後使用此代碼:

SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); 
     mapFragment.getMapAsync(this); 
1

當使用地圖內部片段時,getFragmentManager()可能不起作用。您必須使用getChildFragmentManager()

SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.fragment_track_order_map_fragment); 
mapFragment.getMapAsync(this); 

和下面是我的XML聲明

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

還需要在你的片段實現OnMapReadyCallback。

0

答案很簡單,如果你想添加地圖碎片這個

<fragment 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/map" 
    android:name="com.google.android.gms.maps.SupportMapFragment" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:layout="@layout/fragment_home" /> 

到您的片段:這樣的佈局

<android.support.constraint.ConstraintLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:app="http://schemas.android.com/apk/res-auto" 
     xmlns:tools="http://schemas.android.com/tools" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
tools:context="com.example.android.earthreport.fragments.HomeFragment" 
     tools:layout_editor_absoluteX="8dp" 
     tools:layout_editor_absoluteY="81dp"> 

    <fragment 
xmlns:android="http://schemas.android.com/apk/res/android" 
      xmlns:tools="http://schemas.android.com/tools" 
      android:id="@+id/map" 
      android:name="com.google.android.gms.maps.SupportMapFragment" 
      android:layout_width="0dp" 
      android:layout_height="0dp" 
      app:layout_constraintBottom_toBottomOf="@id/guideline4" 
      app:layout_constraintEnd_toEndOf="parent" 
      app:layout_constraintStart_toStartOf="parent" 
      app:layout_constraintTop_toTopOf="@id/guideline3" 
      tools:layout="@layout/fragment_home" /> 
     </android.support.constraint.ConstraintLayout> 

然後,你必須要後添加此行像這樣膨脹片段

@Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 

     // Find a reference to the {@link ListView} in the layout 
     // Inflate the layout for this fragment 
     // To get the referance we don't have findviewbyId 
     // method in fragment so we use view 
     View view = inflater.inflate(R.layout.fragment_home, container, false); 


      SupportMapFragment mapFragment = (SupportMapFragment) 
        this.getChildFragmentManager() 
        .findFragmentById(R.id.map) 
      mapFragment.getMapAsync(this); 
..... 

進入你的活動:這樣的佈局

<?xml version="1.0" encoding="utf-8"?> 
<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <fragment xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:tools="http://schemas.android.com/tools" 
     android:id="@+id/map" 
     android:name="com.google.android.gms.maps.SupportMapFragment" 
     android:layout_width="0dp" 
     android:layout_height="0dp" 
     app:layout_constraintBottom_toBottomOf="parent" 
     app:layout_constraintEnd_toEndOf="parent" 
     app:layout_constraintStart_toStartOf="parent" 
     app:layout_constraintTop_toTopOf="parent" 
     tools:context="package com.example.android.map" /> 

</android.support.constraint.ConstraintLayout> 

,那麼你必須添加代碼這個塊。

@Override 
     protected void onCreate(@Nullable Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
     setContentView(R.layout.map_activity); 
     SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() 
       .findFragmentById(R.id.map); 
     mapFragment.getMapAsync(this); 
     } 

糾正我,如果我錯了,但總是添加地圖片段後膨脹佈局或設置內容視圖。

1

這個工作對我來說:

SupportMapFragment mapFragment = (SupportMapFragment)getChildFragmentManager() 
      .findFragmentById(R.id.map); 
    mapFragment.getMapAsync(this); 
相關問題