【问题标题】:GoogleMap Fragment returning null object谷歌地图片段返回空对象
【发布时间】:2017-05-12 16:43:19
【问题描述】:

我希望有一个独立于 MainActivity 的类来初始化地图,并有一个用于初始化的静态方法,因此它在整个项目中保持不变,并且任何类都可以使用从类返回的这个 googlemap 对象,我编写了一个单独的类

public class MapFragment extends AppCompatActivity{

public static SupportMapFragment mapFrag;

public static SupportMapFragment GetMapObj() {
   mapFrag = (SupportMapFragment) new MainActivity().
   getSupportFragmentManager().findFragmentById(R.id.frag_map);
}

在 MainActivity 中像这样使用它

SupportMapFragment mapFragment = MapFragment.GetMapObj();
        mapFragment.getMapAsync(this);

我有 2 个 xml 1 用于上面的类和 1 个用于 mainActivity 我不知道我应该把我的

 <fragment
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/frag_map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    tools:context="com.example.sarahn.clientapimap.MainActivity"
    />

说了这么多,我的应用程序因尝试在空对象引用上调用 getAsncMap 的空指针异常而崩溃

}

【问题讨论】:

  • 你考虑过使用onSaveInstanceState函数来存储地图状态吗?
  • 我想要干净的代码,我的 MainActivity 应该排除所有我只想在 MainActivity 中有对象并在其上调用 getAsync 的东西
  • 永远不要使用new 创建活动实例。它将未初始化且无用。
  • @KevinKrumwiede 你能解释一下你的观点吗?
  • Android 框架在创建 Activity 时,会向其中注入 Context 并调用其初始化生命周期方法。如果没有所有这些初始化,getSupportFragmentManager 之类的方法根本无法工作。

标签: java android google-maps android-fragments google-play-services


【解决方案1】:

您收到NullPointerException,因为您的mapFragment 未正确初始化。

改为在您的MainActivity 中初始化SupportMapFragment

main_activity_xml:

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

现在在您的MainActivity

 public class MainActivity extends FragmentActivity implements OnMapReadyCallback{


  SupportMapFragment smp;
  GoogleMap mMap;

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

    @Override
    public void onMapReady(GoogleMap map) {
        mMap = map;
        //map initialized
    }
}

【讨论】:

  • 但正如我之前所说,我希望将这些东西放在另一个类中而不是在 MainActivity 中,我只想在 MainActivity 中的返回对象上调用 getMapAsync
  • 看到这个:stackoverflow.com/questions/25517406/… 地图的静态对象,这不是一个好习惯
  • 为什么我做不到,我想做的事
  • 首先MapFragment.GetMapObj()..永远不会返回一个有效的对象..因为布局还没有膨胀..看这个:android.tutorialhorizon.com/…
【解决方案2】:

如果您希望您的活动在用户在地图中执行某项操作时执行某项操作,请尝试此操作。

public class YourFragment extends Fragment implements OnMapReadyCallback,
    GoogleMap.OnMapClickListener,
    GoogleMap.OnMarkerClickListener{

    private MapFragment mapFragment;
    private GoogleMap mMap;
    private OnMapListener onMapListener;

    public static YourFragment newInstance(){
        return new YourFragment();
    }

    @Override public void onAttach(Context context) {
        super.onAttach(context);
        try {
            this.onMapListener = (OnMapListener)context;
        }
        catch (final ClassCastException e) {
            throw new ClassCastException(context.toString() + " must implement OnMapListener");
        }
    }

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

        mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id. frag_map); 
        mapFragment.getMapAsync(this); //Its async, It could last a little bit and 
        //that is the reason why you are getting NULL,
        // to work Asynchronously you should implement the Callback 'OnMapReadyCallback'.

        return rootView;
    }

    @Override public void onMapReady(GoogleMap googleMap) { 
        mMap = googleMap; 
        mMap.setOnMapClickListener(this);
        mMap.setOnMarkerClickListener(this);
    }

    @Override public void onMapClick(LatLng latLng) {
        onMapListener.onMapClick(latLng);
    }

    @Override public boolean onMarkerClick(Marker marker) {
        onMapListener.onMarkerClick(marker);
    }

    public interface OnMapListener{
        void onMapClick(LatLng latLng);
        void onMarkerClick(Marker marker);
    }
}


public class YourActivity extends AppCompatActivity implements OnMapListener {

    @Override protected void onCreate(Bundle savedInstanceState) {

        ...
        YourFragment newFragment = YourFragment.newInstance();
        ...
    }

    public void onMapClick(LatLng latLng){
    //do something on your activity
    }
    public void onMarkerClick(Marker marker){
    //do something on your activity
    }          
}

【讨论】:

  • 我已经实现了,但正如我之前所说,我希望将这些东西放在另一个类中而不是在 MainActivity 中,我只想在 MainActivity 中的返回对象上调用 getMapAsync
  • 我认为您应该重用 GoogleMap 的对象,而不是 SupportMapFragment 的对象,但我有一个问题,您想在多个活动中重用该对象还是只在一个活动中重用该对象?
  • 我只想拥有干净的代码,以便我的 MainActivity 应该排除所有这些并利用初始化其他类
  • 我更新了我的答案老兄,告诉我你是否想要这样的东西。
【解决方案3】:

您可以扩展SupportMapFragment 并在片段自己的onCreate 方法中初始化地图。这样可以避免将逻辑上属于片段的代码弄乱您的活动。

public class MyMapFragment extends SupportMapFragment {
    @Override
    public void onCreate(final Bundle bundle) {
        super.onCreate(bundle);
        getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(final GoogleMap map) {
                // configure the map here
            }
        });
    }
}

然后像普通的SupportMapFragment 一样将其放入您的活动 XML 中。

<fragment
    android:id="@+id/map"
    android:name="com.myapp.MyMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

如果您仍需要访问活动中的片段,请致电getSupportFragmentManager().findFragmentById(R.id.map)。但是由于片段配置了地图,活动可能不再需要访问它。使用片段的活动通常只是onCreate 调用setContentView

【讨论】:

  • 会与MainActivity分离,在MainActivity中如何使用?
  • @blackHawk 它会在您自己的自定义片段类中,如图所示。我不知道你说的分开是什么意思。该活动可以通过getSupportFragmentManager().findFragmentById(R.id.map) 获得对片段的引用。 Activity 想用它做什么?
【解决方案4】:

问题是您正在尝试创建一个新的上下文,而不是让操作系统来做。您必须在现有上下文中使用 startActivity 才能创建新活动。

至于你想如何获取你的地图对象,这里是一个例子:

public class MapFragment extends AppCompatActivity{

    public static SupportMapFragment mapFrag;

    public static SupportMapFragment GetMapObj(FragmentActivity activity) {
       mapFrag = (SupportMapFragment) activity.
         getSupportFragmentManager().findFragmentById(R.id.frag_map);
    }
}

在你的活动中,只需调用这个:

SupportMapFragment mapFragment = MapFragment.GetMapObj(this);
        mapFragment.getMapAsync(this);

【讨论】:

  • 另外,请记住,这假设您已经将片段附加到此活动的片段管理器。
  • 请更新您的答案,关于将片段附加到活动片段
  • 不确定是否应该推荐静态方法
  • 老实说,这是@blackHawk 代码的补丁,而不是解决方案。正确的解决方案是其他 3 个答案之一。
猜你喜欢
  • 2018-05-16
  • 1970-01-01
  • 2016-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-19
相关资源
最近更新 更多