嵌套片段 - 不能保留嵌套在其他片段中的片段

时间:2015-10-23 14:22:09

标签: android android-fragments illegalstateexception

我有一个由多个嵌套片段组成的Android应用程序,例如我有一组选项卡,然后单击一个选项卡将片段加载到内容区域。

我的一个标签是显示其上的位置的地图,我正在对邮政编码进行地理查找以获取它的坐标。

这一切都有效,现在最后我需要确保如果用户单击地图选项卡并启动异步任务,该任务执行地理查找,设备轮换不会停止此操作。

单击选项卡时加载的地图片段:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = (View)inflater.inflate(R.layout.fragment_locations, container, false);

    // Make sure user's device supports Google play services
    try {
        MapsInitializer.initialize(getActivity());
        mapView = (MapView) rootView.findViewById(R.id.mapView);
        mapView.onCreate(savedInstanceState);
        googleMap = mapView.getMap();
        Log.i(LOG_TAG, "Google play service is available.");

        if(googleMap == null) {
            Toast.makeText(getActivity().getApplicationContext(), "Problem creating Google map", Toast.LENGTH_LONG).show();
        } else {
            googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
               googleMap.getUiSettings().setZoomControlsEnabled(true);                     

            FragmentManager fm = getFragmentManager();
            mRetainedTaskFragment = (LocationNetworkOperationsRetainedFragment) fm.findFragmentByTag(TAG_RETAINED_TASK_FRAGMENT);

            // If the Fragment is non-null, then it is currently being
            // retained across a configuration change.
            if (mRetainedTaskFragment == null) {
                mRetainedTaskFragment = new LocationNetworkOperationsRetainedFragment();
                fm.beginTransaction().add(mRetainedTaskFragment, TAG_RETAINED_TASK_FRAGMENT).commit();
            }
        }
    } catch (Exception e) {
        Log.e(LOG_TAG, "Google play service is not available.");
        Toast.makeText(getActivity().getApplicationContext(), "Google play service is not available", Toast.LENGTH_LONG).show();
    }

    return rootView;
}

我的异步任务:

public class LocationNetworkOperations extends AsyncTask<String, Void, LatLng> {

    @Override
    protected LatLng doInBackground(String... postcodes) {
        Geocoder geocoder = new Geocoder(getActivity().getApplicationContext());
        LatLng coords= null;

        try {
            List<Address> addresses = geocoder.getFromLocationName(postcodes[0], 1);

            if (addresses != null && !addresses.isEmpty()) {
                Address address = addresses.get(0);
                coords = new LatLng(address.getLatitude(), address.getLongitude());
            } else {
                Toast.makeText(getActivity().getApplicationContext(), "Unable to geocode postcode" + postcodes[0], Toast.LENGTH_LONG).show();
            }
        } catch(Exception ioe) {
            ioe.printStackTrace();
        }

        return coords;
    }

    @Override
    protected void onPostExecute(LatLng coords) {
        if(coords != null) {
            Marker mapMarkerHome = googleMap.addMarker(new MarkerOptions().position(coords).title("Home")
                    .snippet("E10 6JQ").icon(BitmapDescriptorFactory
                            .fromResource(R.drawable.home_map_marker)));
            CameraPosition cameraPosition = new CameraPosition.Builder().target(coords).zoom(15).build();
            googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
        }
    }

    @Override
    protected void onPreExecute() {}

    @Override
    protected void onProgressUpdate(Void... values) {}
}

保留的片段:

public class LocationNetworkOperationsRetainedFragment extends Fragment {

interface LocationNetworkOperationsTaskCallbacks {
    void onPreExecute();
    void onProgressUpdate(int percent);
    void onCancelled();
    void onPostExecute();
}

private LocationNetworkOperationsTaskCallbacks mCallbacks;
private LocationsFragment.LocationNetworkOperations mTask;

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    mCallbacks = (LocationNetworkOperationsTaskCallbacks) context;
}

/**
 * This method will only be called once when the retained
 * Fragment is first created.
 */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Retain this fragment across configuration changes.
    setRetainInstance(true);

    // Create and execute the background task.
    mTask = new LocationsFragment().new LocationNetworkOperations();
    mTask.execute("E106JQ");
}

@Override
public void onDetach() {
    super.onDetach();
    mCallbacks = null;
}

}

所以我按照教程编写了一个保留的片段并启动了aysnc任务,但是我遇到了以下异常:

java.lang.IllegalStateException: Can't retain fragements that are nested in other fragments
        at android.support.v4.app.Fragment.setRetainInstance(Fragment.java:820)
        at com.example.android.LocationNetworkOperationsRetainedFragment.onCreate(LocationNetworkOperationsRetainedFragment.java:37)
        at android.support.v4.app.Fragment.performCreate(Fragment.java:1939)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:988)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1207)
        at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
        at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1572)
        at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:493)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

为什么不能保留片段,如果它是嵌套的,并且有解决方案吗?

2 个答案:

答案 0 :(得分:1)

尝试使用FragmentManager.saveFragmentInstanceState(Fragment)检索片段状态。返回值实现了Parcelable,因此您可以将它放在Bundle中。

对于恢复,您可以在使用Fragment.setInitialSavedState(Fragment.SavedState)创建片段后提供状态。

答案 1 :(得分:-1)

Can't retain fragements that are nested in other fragments

这是嵌套片段的限制。我猜你的一个或多个子片段在代码中的某处有setRetainInstance(true)。您需要删除它以防止错误。

相关问题