我的活动与导航抽屉和 HomeFragment 。
HomeFragment 包含两个嵌套片段(子片段): SupportMapFragment 和 ActionFragment 。
我在 HomeFragment 中将GoogleMap对象 sMap
声明为静态,因此可以通过嵌套片段 ActionFragment
第一次运行时一切正常。可以在 ActionFragment 中操作地图。但是当HomeFragment被删除并在以后重新加载时,地图只能从HomeFragment(父片段)修改,而不能再从ActionFragment(嵌套片段)修改。
我无法理解为什么在重新加载片段时,在第一个实例中起作用的东西不起作用。以下是我保持最低限度的代码,以便于理解。
HomeFragment.java (父片段)
public class HomeFragment extends Fragment {
private static GoogleMap sMap;
public static GoogleMap getMap() {
return sMap;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate layout
return inflater.inflate(R.layout.f_home, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
// Obtain the GoogleMap object
try {
if (sMap == null) {
sMap = ((SupportMapFragment) getActivity().getSupportFragmentManager()
.findFragmentById(R.id.home_map)).getMap();
}
} catch (Exception e) {
e.printStackTrace();
}
// Load child fragment
if (savedInstanceState == null) {
Fragment _actionFragment = new ActionFragment();
FragmentTransaction _ft = getChildFragmentManager().beginTransaction();
_ft.replace(R.id.action_container_bottom, _actionFragment);
_ft.commit();
}
}
@Override
public void onDestroyView(){
super.onDestroyView();
// Remove the map fragment to prevent errors on the next load
if(sMap != null){
try {
getActivity().getSupportFragmentManager()
.beginTransaction()
.remove(getActivity().getSupportFragmentManager()
.findFragmentById(R.id.home_map))
.commit();
sMap = null;
} catch (Exception e){}
}
}
}
f_home.xml (父片段的布局)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/home_map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:id="@+id/action_container_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
</RelativeLayout>
ActionFragment.java (嵌套或子片段)
public class ActionFragment extends Fragment {
private static GoogleMap sMap = HomeFragment.getMap();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.f_action, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
// check if map is created successfully or not
if (sMap != null) {
sMap.clear();
sMap.setPadding(0, 0, 0, 300);
sMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
sMap.setBuildingsEnabled(false);
sMap.setMyLocationEnabled(false);
sMap.getUiSettings().setRotateGesturesEnabled(false);
sMap.getUiSettings().setTiltGesturesEnabled(false);
sMap.getUiSettings().setZoomControlsEnabled(false);
sMap.moveCamera(CameraUpdateFactory.zoomTo(12));
}
}
}
任何帮助都会受到极大的赞赏,因为我很长时间都在努力解决这个问题。谢谢!
答案 0 :(得分:7)
问题是类加载器只加载ActionFragment
一次,这就是为什么静态字段只在第一轮初始化。
首次运行会发生什么:
1)HomeFragment#onActivityCreated()
HomeFragment#sMap
为空 - &gt;通过findViewById()HomeFragment#sMap
= [1] 2)ActionFragment
ActionFragment#sMap
为空 - &gt;从HomeFragment.getMap()
ActionFragment#sMap
= [1] ......家被毁......
3)HomeActivity#onDestroyView()
HomeFragment#sMap
= null ...家庭得到重建......
4)HomeFragment#onActivityCreated()
HomeFragment#sMap
为空 - &gt;通过findViewById()HomeFragment#sMap
= [2] 由于课程ActionFragment
已经加载到内存中,因此无法再次加载课程,因此静态字段ActionFragment#sMap
的代码将不再次执行。它仍在引用旧的(无效的)[1]实例。
要解决此问题,您可以执行以下操作:
public class ActionFragment extends Fragment {
private GoogleMap mMap;
public void onAttach(Activity activity) {
super.onAttach(activity);
mMap = HomeFragment.getMap();
}
public void onDetach() {
super.onDetach() {
mMap = null;
}
}
使用此代码,每次附加ActionFragment
时,它都会请求HomeFragment
的最新地图实例。
答案 1 :(得分:4)
糟糕的设计。 保持静态var以存储对地图的引用是错误的。假设您有两个HomeFragment或几个包含HomeFragment的活动。它不会起作用。
我认为您应该使用标签来查找片段。或者更好地在活动中创建一些接口来实现片段之间的通信。无论如何,你不能以你的方式使用静态字段作为地图。
您可以使用此代码:
((SupportMapFragment) getActivity().getSupportFragmentManager()
.findFragmentById(R.id.home_map)).getMap();
每次需要时获取地图。
答案 2 :(得分:3)
问题是您尝试将包含SupportMapFragment
的布局扩展到另一个片段HomeFragment
。嵌套片段仅以编程方式支持。来自docs:
注意:在布局时,您无法将布局扩展为片段 包括一个片段。仅在添加时支持嵌套片段 一个动态的片段。
<强> f_home.xml 强>
<!--<fragment
android:id="@+id/home_map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />-->
<FrameLayout
android:id="@+id/home_map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<强> HomeFragment 强>
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
// Obtain the GoogleMap object
try {
if (sMap == null) {
/*sMap = ((SupportMapFragment) getActivity().getSupportFragmentManager()
.findFragmentById(R.id.home_map)).getMap();*/
mapFragment = new SupportMapFragment();
sMap = mapFragment.getMap();
getChildFragmentManager()
.beginTransaction()
.replace(R.id.home_map, mapFragment)
.commit();
}
} catch (Exception e) {
e.printStackTrace();
}
// Load child fragment
if (savedInstanceState == null) {
Fragment _actionFragment = new ActionFragment();
FragmentTransaction _ft = getChildFragmentManager().beginTransaction();
_ft.replace(R.id.action_container_bottom, _actionFragment);
_ft.commit();
}
}
@Override
public void onDestroyView(){
super.onDestroyView();
// Remove the map fragment to prevent errors on the next load
if(sMap != null){
try {
/*getActivity().getSupportFragmentManager()
.beginTransaction()
.remove(getActivity().getSupportFragmentManager()
.findFragmentById(R.id.home_map))
.commit();*/
getChildFragmentManager()
.beginTransaction()
.remove(mapFragment)
.commit();
sMap = null;
mapFragment = null;
} catch (Exception e){}
}
}
在ActionFragment
而不是维护从GoogleMap
获得的HomeFragment
的静态引用,请使用findFragmentById
api。