在android java中正确保存fragment状态

问题描述 投票:0回答:1

我正在使用 Android Studio 用 Java 实现 Android 应用程序。我们使用 Jetpack Compose 遵循 MVVM 架构,并且有一个包含各种片段的导航栏,包括主页片段等。在主页片段中,我有一个使用 OsmDroid 实现的地图。

我的问题是,在使用 homefragment.xml、HomeFragment.java、HomeViewModel.java、MainActivity.java 和 MainActivity.xml 组织项目后,我尝试通过 MainActivity 管理权限请求,并对其他类执行必要的操作。该应用程序可以工作,但是当我将地图移动到特定位置,然后使用导航栏更改片段时,返回地图会将其值重置为我的活动位置所在的默认位置。

为了解决这个问题,我尝试使用 onSaveInstanceState(Bundle outState) 和 onCreate() 方法来实施适当的更正。然而,在调试过程中,我注意到 onCreate 中 saveInstanceState 不为 null 的代码部分永远不会到达,这让我的尝试显得徒劳。

这是我的 homefragment.java 类,也许我不明白 Bundle outState 和 Bundle savingInstanceState 之间的关系如何工作:

package com.seaguard.ui.home;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

import com.seaguard.databinding.FragmentHomeBinding;

import org.osmdroid.api.IGeoPoint;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapController;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider;
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay;


public class HomeFragment extends Fragment {
    private FragmentHomeBinding binding;
    private MapView map;

    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if(savedInstanceState == null) {
            System.out.println("BBB");
            HomeViewModel homeViewModel = new ViewModelProvider(requireActivity()).get(HomeViewModel.class);

            binding = FragmentHomeBinding.inflate(inflater, container, false);
            View root = binding.getRoot();

            // Map
            map = binding.map;
            map.setTileSource(TileSourceFactory.MAPNIK);
            map.setBuiltInZoomControls(false);
            map.setMultiTouchControls(true);

            MapController mapController = (MapController) map.getController();
            mapController.setCenter(new GeoPoint(41.8902, 12.4922)); // Rome
            mapController.setZoom(16);

            homeViewModel.setCallBack(() -> {
                //provider.addLocationSource(LocationManager.NETWORK_PROVIDER);
                MyLocationNewOverlay location = new MyLocationNewOverlay(new GpsMyLocationProvider(map.getContext()), map);
                location.enableMyLocation();
                map.getOverlays().add(location);

                location.runOnFirstFix(() -> {
                    requireActivity().runOnUiThread(() -> map.getController().animateTo(location.getMyLocation()));
                });
                return location;
            });
            if (homeViewModel.permissionsRequested()) homeViewModel.setLocation();
            return root;
        }else{

            System.out.println("AAAA");

            View root = binding.getRoot();

            double latitude = savedInstanceState.getDouble("latitude", 41.8902);
            double longitude = savedInstanceState.getDouble("longitude", 12.4922);
            int zoom_level = savedInstanceState.getInt("zoom_level", 16);
            float map_orientation = savedInstanceState.getFloat("map_orientation", 0);

            GeoPoint restoredCenter = new GeoPoint(latitude, longitude);

            map.getController().setCenter(restoredCenter);
            map.getController().setZoom(zoom_level);
            map.setMapOrientation(map_orientation);

            return root;
        }
    }


    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);

            IGeoPoint center = map.getMapCenter();
            outState.putDouble("latitude", center.getLatitudeE6() / 1e6);
            outState.putDouble("longitude", center.getLongitudeE6() / 1e6);

            outState.putInt("zoom_level", map.getZoomLevel());

            outState.putFloat("map_orientation", map.getMapOrientation());

    }

}

请注意,我使用这些 println 进行调试,似乎 AAA 永远不会在 logcat 中打印,因此代码永远不会被执行

java android fragment lifecycle onsaveinstancestate
1个回答
0
投票

我认为现在你可以尝试通过共享偏好来做到这一点,例如:-

//设置数据

 SharedPreferences data = getSharedPreferences("MapData", MODE_PRIVATE);
  SharedPreferences.Editor data_editor =data.edit();
  //putting double in string as it does not store double value
  data_editor.putString("latitude", String.valueOf(data1 / 1e6));
  data_editor.putString("longitude", String.valueOf(data2 / 1e6));
  data_editor.putInt("zoom_level", map.getZoomLevel());
  data_editor.putFloat("map_orientation", map.getMapOrientation());
  data_editor.apply();

//获取数据

 SharedPreferences data = getSharedPreferences("MapData", MODE_PRIVATE);
    lat= Double.valueOf(data.getString("latitude","0.0"));
    lon= Double.valueOf(data.getString("longitude","0.0"));
    //do it for others too 

如果获得数据则加载地图

每次打开应用程序时请务必重置数据

SharedPreferences data = getSharedPreferences("MapData", MODE_PRIVATE);
    SharedPreferences.Editor data_editor =data.edit();
    data_editor.clear();
    data_editor.commit();

其他虎钳它将加载上次保存的旧数据 完成后您还可以清除数据

© www.soinside.com 2019 - 2024. All rights reserved.