在应用启动时让标签预加载其片段并使标签保存状态

时间:2017-04-08 21:25:14

标签: android google-maps android-fragments

我有3个标签:

  • 主页
  • Google地图
  • 设置

我有一个主要活动,它有一个TabLayout来显示3个标签:

public class MainActivity extends AppCompatActivity implements MyMapFragment.OnFragmentInteractionListener, SettingsFragment.OnFragmentInteractionListener {

private static final int INDEX_HOME_FRAGMENT = 0;
private static final int INDEX_MAP_FRAGMENT = 1;
private static final int INDEX_SETTINGS_FRAGMENT = 2;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

    tabLayout.addTab(tabLayout.newTab().setText("Home"));
    tabLayout.addTab(tabLayout.newTab().setText("Map"));
    tabLayout.addTab(tabLayout.newTab().setText("Settings"));

    tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {

            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();


            switch(tab.getPosition()) {

                case INDEX_HOME_FRAGMENT:
                    HomeFragment homeFragment = new HomeFragment();
                    transaction.replace(R.id.frame_layout, homeFragment);
                    // Commit the transaction
                    transaction.commit();

                    break;

                case INDEX_MAP_FRAGMENT:
                    MyMapFragment myMapFragment = new MyMapFragment();

                    transaction.replace(R.id.frame_layout, myMapFragment);
                    // Commit the transaction
                    transaction.commit();

                    break;

                case INDEX_SETTINGS_FRAGMENT:
                    SettingsFragment settingsFragment = new SettingsFragment();
                    transaction.replace(R.id.frame_layout, settingsFragment);
                    // Commit the transaction
                    transaction.commit();
                    break;

                default:
                    //error occured here
                    Log.e("Error occured = ", " TAB_ERROR");
                    break;
            }
        }
    });

    // Check that the activity is using the layout version with
    // the fragment_container FrameLayout
    if (findViewById(R.id.frame_layout) != null) {
        if (savedInstanceState != null) {
            return;
        }
        HomeFragment homeFragment = new HomeFragment();
        // Add the fragment to the 'fragment_container' FrameLayout
        getSupportFragmentManager().beginTransaction()
                .add(R.id.frame_layout, homeFragment ).commit();
    }
}

@Override
public void onFragmentInteraction(Uri uri) {
    //do nothing
}
}

此活动还会在单击选项卡时进行处理。单击选项卡时,它应显示FrameLayout中的片段 一切正常。唯一的问题是当我点击地图标签时,Google地图会一直刷新 我希望地图在应用程序启动时预加载,因此当用户单击地图选项卡时,已经加载了地图shoudl。当用户离开地图选项卡并返回时,它应该像以前一样保存地图。目前,当用户返回地图选项卡时,地图会重新加载,并且需要一段时间才能加载地图。

这是我的地图片段:

public class MyMapFragment extends SupportMapFragment
        implements OnMapReadyCallback,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener {

    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
    GoogleMap mGoogleMap;
    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    Marker lastOpenned = null;


    @Override
    public void onResume() {
        super.onResume();

        setUpMapIfNeeded();
    }

    private void setUpMapIfNeeded() {

        if (mGoogleMap == null) {
            getMapAsync(this);
        }
    }

    @Override
    public void onPause() {
        super.onPause();

        //stop location updates when Activity is no longer active
        if (mGoogleApiClient != null) {
            //LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {

        mGoogleMap = googleMap;


        LatLngBounds.Builder builder = new LatLngBounds.Builder();

        mGoogleMap.addMarker(new MarkerOptions()
                .position(new LatLng(40.76793169992044, -73.98180484771729))
                .title("San Francisco"));
        mGoogleMap.addMarker(new MarkerOptions()
                .position(new LatLng(41.76793169992044, -72.98180484771729))
                .title("Las Vegas"));

        builder.include(new LatLng(40.76793169992044, -73.98180484771729));
        builder.include(new LatLng(41.76793169992044, -72.98180484771729));
        LatLngBounds bounds = builder.build();

        mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 200));

        mGoogleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
            public boolean onMarkerClick(Marker marker) {

                return true;
            }
        });

        //Initialize Google Play Services
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(getActivity(),
                    Manifest.permission.ACCESS_FINE_LOCATION)
                    == PackageManager.PERMISSION_GRANTED) {
                //Location Permission already granted
                buildGoogleApiClient();
                mGoogleMap.setMyLocationEnabled(true);
            } else {
                //Request Location Permission
                checkLocationPermission();
            }
        } else {
            buildGoogleApiClient();
            mGoogleMap.setMyLocationEnabled(true);
        }
    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnected(Bundle bundle) {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(1000);
        mLocationRequest.setFastestInterval(1000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        if (ContextCompat.checkSelfPermission(getActivity(),
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }


    @Override
    public void onConnectionSuspended(int i) {
    }

    @Override
    public void onLocationChanged(Location location) {

    }

    private void checkLocationPermission() {
        if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
                    Manifest.permission.ACCESS_FINE_LOCATION)) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.
                new AlertDialog.Builder(getActivity())
                        .setTitle("Location Permission Needed")
                        .setMessage("This app needs the Location permission, please accept to use location functionality")
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                //Prompt the user once explanation has been shown
                                ActivityCompat.requestPermissions(getActivity(),
                                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                        MY_PERMISSIONS_REQUEST_LOCATION);
                            }
                        })
                        .create()
                        .show();


            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted, yay! Do the
                    // location-related task you need to do.
                    if (ContextCompat.checkSelfPermission(getActivity(),
                            Manifest.permission.ACCESS_FINE_LOCATION)
                            == PackageManager.PERMISSION_GRANTED) {

                        if (mGoogleApiClient == null) {
                            buildGoogleApiClient();
                        }
                        mGoogleMap.setMyLocationEnabled(true);
                    }

                } else {

                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                    Toast.makeText(getActivity(), "permission denied", Toast.LENGTH_LONG).show();
                }
                return;
            }

            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }


    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }
}

1 个答案:

答案 0 :(得分:0)

I would suggest not making new MyMapFragment() every time you click the tab if you don't want the map to reload.

A simple way to do that is a simple wrapper Fragment holder class.

public class MainActivity extends AppCompatActivity 
    implements MyMapFragment.OnFragmentInteractionListener, SettingsFragment.OnFragmentInteractionListener {

    static class FragmentTab {
        String name;
        Fragment frag;

        public FragmentTab(String name, Fragment f) {
            this.name = name;
            this.frag = f;
        }
    }

    // These are only created once, not per-click
    private List<FragmentTab> tabs = Arrays.asList(
        new FragmentTab("Home", new HomeFragment()),
        new FragmentTab("Map", new MyMapFragment()),
        new FragmentTab("Settings", new SettingsFragment()),
    );

Then, you can iterate and index that list to clean up the rest of your code

for (FragmentTab tab : tabs) {
    tabLayout.addTab(tabLayout.newTab().setText(tab.name));
}

tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {

        getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.frame_layout, tabs.get(tab.getPosition()).frag)
            .commit();
    }
};

A LinkedHashMap<String, Fragment> would also work, but replacing tab.getPosition() for tab.getTitle() (I think)