簡體   English   中英

在片段之間切換時如何保存地圖的狀態?

[英]How to save the state of the map when switching between fragments?

當我將片段切換到另一個片段並返回到地圖時,則 Google Map _map 等於 null。

假設我在地圖周圍移動,然后移動到另一個片段並返回到地圖。 當我回到卡上時,它已超載。

如何解決這個問題呢。 非常感謝 ! 然后我不知道該怎么辦。 你有哪些選擇? 也許有人已經在這方面工作了?

    public class MapFragment extends Fragment implements OnMapReadyCallback {

    private GoogleMap _map;

    // The geographical location where the device is currently located. That is, the last-known
    // location retrieved by the Fused Location Provider.
    private Location _mLastKnownLocation;

    SharedManager _manager;
    Connect _connect;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        _manager = new SharedManager(getActivity());
        _connect = new Connect();

        // Retrieve location and camera position from saved instance state.
        if (savedInstanceState != null) {
            _mLastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION);
            _mCameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION);
        }

        // Construct a FusedLocationProviderClient.
        _mFusedLocationProviderClient = 
        LocationServices.getFusedLocationProviderClient(getActivity());
        Log.d(TAG, "onCreate");
       }

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_map, container, false);
        //BuildMap
        initializeMap();
        Log.d(TAG, "onCreateView");
        return root;
    }

    /**
     * Saves the state of the map when the activity is paused.
     */
    @Override
    public void onSaveInstanceState(Bundle outState) {
        if (_map != null) {
            outState.putParcelable(KEY_CAMERA_POSITION, _map.getCameraPosition());
            outState.putParcelable(KEY_LOCATION, _mLastKnownLocation);
            super.onSaveInstanceState(outState);
        }
        Log.d(TAG, "onSaveInstanceState");
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        _map = googleMap;

        _map.getUiSettings().setZoomControlsEnabled(false);
        _map.setMapType(GoogleMap.MAP_TYPE_NORMAL);

        // Prompt the user for permission.
        getLocationPermission();

        // Turn on the My Location layer and the related control on the map.
        updateLocationUI();

        // Get the current location of the device and set the position of the map.
        getDeviceLocation();
    }

    /**
     * Gets the current location of the device, and positions the map's camera.
     */
    private void getDeviceLocation() {
        /*
         * Get the best and most recent location of the device, which may be null in rare
         * cases when a location is not available.
         */
        try {
            if (_mLocationPermissionGranted) {
                Task<Location> locationResult = _mFusedLocationProviderClient.getLastLocation();
                locationResult.addOnCompleteListener(getActivity(), new OnCompleteListener<Location> 
                () {
                    @Override
                    public void onComplete(@NonNull Task<Location> task) {
                        if (task.isSuccessful()) {
                            // Set the map's camera position to the current location of the device.
                            _mLastKnownLocation = task.getResult();
                            if (_mLastKnownLocation != null) {
                                _map.moveCamera(CameraUpdateFactory.newLatLngZoom(
                                        new LatLng(_mLastKnownLocation.getLatitude(),
                                                _mLastKnownLocation.getLongitude()), 15));
                            }
                        } else {
                            Log.d(TAG, "Current location is null. Using defaults.");
                            Log.e(TAG, "Exception: %s", task.getException());
                            _map.moveCamera(CameraUpdateFactory
                                    .newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
                            _map.getUiSettings().setMyLocationButtonEnabled(false);
                        }
                    }
                });
            }
        } catch (SecurityException e) {
            Log.e("Exception: %s", e.getMessage());
        }
    }

    /**
     * Prompts the user for permission to use the device location.
     */
    private void getLocationPermission() {
        /*
         * Request location permission, so that we can get the location of the
         * device. The result of the permission request is handled by a callback,
         * onRequestPermissionsResult.
         */
        if (ContextCompat.checkSelfPermission(
                this.getActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            _mLocationPermissionGranted = true;

        } else {
            ActivityCompat.requestPermissions(this.getActivity(),
                    new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
                    PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
            updateLocationUI();
        }
    }

    /**
     * Handles the result of the request for location permissions.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        _mLocationPermissionGranted = false;
        switch (requestCode) {
            case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    _mLocationPermissionGranted = true;
                }
            }
        }
        updateLocationUI();
    }

    private void updateLocationUI() {
        if (_map == null) {
            return;
        }
        try {
            if (_mLocationPermissionGranted) {
                _map.setMyLocationEnabled(true);
                _map.getUiSettings().setMyLocationButtonEnabled(true);
            } else {
                _map.setMyLocationEnabled(false);
                _map.getUiSettings().setMyLocationButtonEnabled(false);
                _mLastKnownLocation = null;
                getLocationPermission();
            }
        } catch (SecurityException e) {
            Log.e("Exception: %s", e.getMessage());
        }
    }

    // Build the map.
    private void initializeMap() {
        if (_map == null) {
            SupportMapFragment mapFrag = (SupportMapFragment)
                    getChildFragmentManager().findFragmentById(R.id.map_View);
            assert mapFrag != null;
            mapFrag.getMapAsync(this);
        }
    }

}

這是一個簡單的Fragment間通信問題。 您在此處有多種選擇:

1) 應用其中一種 MV* 方法 (MVP/MVVM/MVI),它將表示層與所有邏輯和視圖分開。 這些相當復雜,我無法在這里詳細解釋。 另外,如果你熟悉這些,你一開始就不會問這個問題。

2) 最簡單(不是最好)的方法是使用 Application 類(假設它遵循Singleton模式),或者您可以使用的幾乎任何其他Singleton類。 只需將數據保存在Fragment A 中並從Fragement B 中檢索。 這有缺點,因為您增加了實例之間的內聚力並依賴於Singleton模式。

3)另一種簡單且更可取的方法是使用簡單的接口(回調)在您的ActivityFragment之間建立雙向通信。 只需在Activity聲明一個回調接口(或實現它)並將其傳遞給Fragments 因此,現在您可以在它們之間傳輸並在Fragment更改期間將數據存儲在Activity中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM