Как НЕ воссоздать фрагменты в ViewPager - PullRequest
0 голосов
/ 26 мая 2019

Я новичок во фрагментах и ​​это так запутанно.У меня есть действие с двумя фрагментами в ViewPager.. ViewPager установлено в TabsLayout.Я использую FragmentStatePagerAdapter.В каждом из этих фрагментов у меня есть RecyclerView, который заполняет список элементов, хранящихся на сервере.

Задача 1

Фрагменты восстанавливаются несколько раз (примерно каждые 20 секунд) с одними и теми же данными.

Что я хочу

Я хочу, чтобы каждый фрагмент был воссоздан только тогда, когда пользователь перешел к нему.Таким образом, он может содержать последние данные, загруженные с веб-сервера.

Задача 2

Когда я просматриваю второй фрагмент, воссоздание всех фрагментов перемещает менявернуться к первому фрагменту.Извините, я не знаю профессиональных терминов, которые можно использовать для описания этого.Я автоматически возвращаюсь к первому фрагменту каждый раз, когда фрагменты воссоздаются.Первый фрагмент - это фрагмент, который загружается при первом создании действия.

Что я хочу

Я хочу, чтобы пользователь оставался в одном и том же фрагменте так долгокак он / она хочет, чтобы автоматическое воссоздание не происходило (ну, как я уже говорил выше, воссоздание должно происходить только при переходе пользователя к нему.).

NOTE

Оба фрагмента идентичны, поэтому я поделюсь кодом только для одного фрагмента.

Вот моя активность:

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener, OneFragment.OnFragmentInteractionListener, TwoFragment.OnFragmentInteractionListener {

    private final int MIN_TIME_BW_UPDATES = 0;
    private final float MIN_DISTANCE_CHANGE_FOR_UPDATES = 0;
    private final long ONE_MEGABYTE = 1024 * 1024;
    private static final int TWO_MINUTES = 1000 * 60 * 2;
    private final int REQUEST_CHECK_SETTINGS = 1;

    private Toolbar toolbar;
    private TabLayout tabLayout;
    private ViewPager viewPager;
    private LocationManager locationManager;
    private LocationListener locationListener;
    private boolean permission, isGPSEnabled, isNetworkEnabled;
    private FirebaseFirestore mDatabase;
    private StorageReference storageRef;
    private Long act_geo_limit;
    private Map<String, Object> user;

    private Location currentBestLocation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        viewPager = (ViewPager) findViewById(R.id.viewpager);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(MainActivity.this, CreatPostActivity.class));
            }
        });

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        final View hView = navigationView.getHeaderView(0);

        mDatabase = FirebaseFirestore.getInstance();
        storageRef = FirebaseStorage.getInstance().getReference();

        user = new HashMap<>();

        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        // Define a listener that responds to location updates
        locationListener = new LocationListener() {
            public void onLocationChanged(Location location) {
                // Called when a new location is found by the network location provider.
                makeUseOfNewLocation(location);

                TextView loc = hView.findViewById(R.id.location);
                try {
                    List<Address> addressList = getAddressForLocation(MainActivity.this, currentBestLocation);
                    loc.setText(addressList.get(0).getAddressLine(0));
                }catch (Exception e){
                    Toast.makeText(MainActivity.this, "Please reboot this device", Toast.LENGTH_LONG).show();
                    e.printStackTrace();
                }


                mDatabase
                        .collection("Users")
                        .document(FirebaseAuth.getInstance().getUid())
                        .get()
                        .addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                            @Override
                            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                                user = task.getResult().getData();
                                act_geo_limit = ((Long) user.get("act_geo_limit"));
                                String p1 = user.get("profile_image_path").toString();
                                storageRef.child(p1).getBytes(ONE_MEGABYTE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
                                    @Override
                                    public void onSuccess(byte[] bytes) {
                                        Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

                                        ImageView imageView = hView.findViewById(R.id.imageView);
                                        //Set Profile pic
                                        imageView.setImageBitmap(bitmap);

                                    }
                                });
                                TextView userName = hView.findViewById(R.id.user_name);
                                userName.setText(user.get("user_name").toString());

                                Bundle bundle=new Bundle();
                                bundle.putString("latitude", String.valueOf(currentBestLocation.getLatitude()));
                                bundle.putString("longitude", String.valueOf(currentBestLocation.getLongitude()));
                                bundle.putString("act_geo_limit", String.valueOf(act_geo_limit));

                                setupViewPager(viewPager, bundle);

                                tabLayout = (TabLayout) findViewById(R.id.tabs);
                                tabLayout.setupWithViewPager(viewPager);

                            }
                        });
            }

            public void onStatusChanged(String provider, int status, Bundle extras) {}

            public void onProviderEnabled(String provider) {

            }

            public void onProviderDisabled(String provider) {

            }
        };


        if (isDevMode()) {
            Toast.makeText(this, "Please turn off Developer Options", Toast.LENGTH_LONG).show();
            FirebaseAuth.getInstance().signOut();
            startActivity(new Intent(MainActivity.this, LoginActivity.class));
        } else {
            boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            if (isGpsEnabled || isNetworkEnabled) {
                //Toast.makeText(this, "GPS is Enabled in your device", Toast.LENGTH_SHORT).show();
                if ( ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) {

                    ActivityCompat.requestPermissions(this, new
                            String[]{Manifest.permission.ACCESS_FINE_LOCATION},REQUEST_CHECK_SETTINGS);
                }
            } else {
                Toast.makeText(this, "Enable Location Services on your device", Toast.LENGTH_SHORT).show();
                FirebaseAuth.getInstance().signOut();
                startActivity(new Intent(MainActivity.this, LoginActivity.class));

            }
        }

        if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
            Log.d("NETWORK ENABLED", "TRUE");
            isNetworkEnabled = true;
        } else {
            Log.d("NETWORK ENABLED", "FALSE");
        }

        if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            Log.d("GPS ENABLED", "TRUE");
            isGPSEnabled = true;
        } else {
            Log.d("GPS ENABLED", "FALSE");
        }

        currentBestLocation = getLastBestLocation();
        if (currentBestLocation != null){
            TextView location = hView.findViewById(R.id.location);
            try {
                List<Address> addressList = getAddressForLocation(this, currentBestLocation);
                location.setText(addressList.get(0).getAddressLine(1));
            }catch (Exception e){
                showRebootAlertToUser();
                e.printStackTrace();
            }
        }

        navigationView.setNavigationItemSelectedListener(this);
        listenForLocationUpdates();

    }

    private void showRebootAlertToUser(){
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setMessage("GeoCoder Error: Please restart this device.")
                .setCancelable(false)
                .setNegativeButton("Got it",
                new DialogInterface.OnClickListener(){
                    public void onClick(DialogInterface dialog, int id){
                        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
                        homeIntent.addCategory( Intent.CATEGORY_HOME );
                        homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        startActivity(homeIntent);
                    }
                });
        AlertDialog alert = alertDialogBuilder.create();
        alert.show();
    }

    @android.annotation.TargetApi(17) public boolean isDevMode() {

        return false;
        /*
        if(Integer.valueOf(android.os.Build.VERSION.SDK) == 16) {
            return android.provider.Settings.Secure.getInt(getApplicationContext().getContentResolver(),
                    android.provider.Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED , 0) != 0;
        } else if (Integer.valueOf(android.os.Build.VERSION.SDK) >= 17) {
            return android.provider.Settings.Secure.getInt(getApplicationContext().getContentResolver(),
                    android.provider.Settings.Global.DEVELOPMENT_SETTINGS_ENABLED , 0) != 0;
        } else return false;
        */
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CHECK_SETTINGS:
                if (grantResults.length> 0) {
                    boolean permission = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                    if (permission) {
                        Toast.makeText(getApplicationContext(), "Permission Granted", Toast.LENGTH_LONG).show();
                    } else {
                        FirebaseAuth.getInstance().signOut();
                        startActivity(new Intent(MainActivity.this, LoginActivity.class));
                    }
                }
                break;

        }
    }

    public List<Address> getAddressForLocation(Context context, Location location) throws IOException {

        if (location == null) {
            return null;
        }
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        int maxResults = 1;

        Geocoder gc = new Geocoder(context, Locale.getDefault());
        List<Address> addresses = gc.getFromLocation(latitude, longitude, maxResults);

        if (addresses.size() > 0) {
            return addresses;
        } else {
            return null;
        }
    }

    protected boolean isBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            // A new location is always better than no location
            return true;
        }

        // Check whether the new location fix is newer or older
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
        boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
        boolean isNewer = timeDelta > 0;

        // If it's been more than two minutes since the current location, use the new location,
        // because the user has likely moved.
        if (isSignificantlyNewer) {
            return true;
            // If the new location is more than two minutes older, it must be worse.
        } else if (isSignificantlyOlder) {
            return false;
        }

        // Check whether the new location fix is more or less accurate
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 200;

        // Check if the old and new location are from the same provider
        boolean isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());

        // Determine location quality using a combination of timeliness and accuracy
        if (isMoreAccurate) {
            return true;
        } else if (isNewer && !isLessAccurate) {
            return true;
        } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
            return true;
        }
        return false;
    }

    // Checks whether two providers are the same
    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }

    /**
    * @return the last know best location
    */

    private Location getLastBestLocation() {
        if ( ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_COARSE_LOCATION ) == PackageManager.PERMISSION_GRANTED )
        {
            Location locationGPS = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            Location locationNet = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            long GPSLocationTime = 0;
            if (null != locationGPS) {
                GPSLocationTime = locationGPS.getTime();
            }

            long NetLocationTime = 0;

            if (null != locationNet) {
                NetLocationTime = locationNet.getTime();
            }

            if (0 < GPSLocationTime - NetLocationTime) {
                return locationGPS;
            } else {
                return locationNet;
            }
        }

        return null;
    }

    private void makeUseOfNewLocation(Location location) {
        if ( isBetterLocation(location, getLastBestLocation()) ) {
            currentBestLocation = location;
            //Log.d("LOCATION+++++", "used");
        } else {
            currentBestLocation = getLastBestLocation();
            //Log.d("LOCATION+++++", "reused");
        }
    }

    private void listenForLocationUpdates(){

        //Toast.makeText(CreatPostActivity.this, "got in", Toast.LENGTH_LONG).show();
        if ( ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED ) {
            if (!isGPSEnabled && !isNetworkEnabled) {
                // No network provider is enabled
            } else {
                if (isNetworkEnabled) {
                    //Toast.makeText(CreatPostActivity.this, "Listen enabled", Toast.LENGTH_LONG).show();
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, locationListener);
                }


                // If GPS enabled, get latitude/longitude using GPS Services
                if (isGPSEnabled) {

                    locationManager.requestLocationUpdates(
                            LocationManager.GPS_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, locationListener);

                }

            }
        }
    }


    private void setupViewPager(ViewPager viewPager, Bundle bundle) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        OneFragment oneFragment = new OneFragment();
        oneFragment.setArguments(bundle);
        TwoFragment twoFragment = new TwoFragment();
        twoFragment.setArguments(bundle);
        adapter.addFragment(oneFragment, "Popular");
        adapter.addFragment(twoFragment, "Recent");
        viewPager.setOffscreenPageLimit(2);
        viewPager.setAdapter(adapter);
    }

    @Override
    public void onFragmentInteraction(Uri uri) {

    }

    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {

    }

    class ViewPagerAdapter extends FragmentStatePagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

        public ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {

            Log.d("Taggggggg", "God is good");
            return mFragmentList.get(position);

        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        public void addFragment(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
        }
    }


    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {


            return true;

        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_home) {
            DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
            drawer.closeDrawer(GravityCompat.START);

        } else if (id == R.id.nav_wall) {
            startActivity(new Intent(this, MyWallActivity.class));

        } else if (id == R.id.nav_messages) {
            Toast.makeText(this, "This service is not available", Toast.LENGTH_SHORT).show();

        } else if (id == R.id.nav_ver) {

            startActivity(new Intent(this, AdBriefingActivity.class));

        } else if (id == R.id.nav_invite) {

            Toast.makeText(this, "This service is not available", Toast.LENGTH_SHORT).show();

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
}

Вот один из моих фрагментов

        public class OneFragment extends Fragment {
            // TODO: Rename parameter arguments, choose names that match
            // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
            private static final String ARG_PARAM1 = "param1";
            private static final String ARG_PARAM2 = "param2";

            // TODO: Rename and change types of parameters
            private String mParam1;
            private String mParam2;

            private RecyclerView recycler;

            private View view;

            private Bundle bundle;
            private List<Post> postList,sortedPostList;
            private List<String>  postIdList;

            private PostAdapter adapter;

            private GeoQueryDataEventListener listener;

            private GeoQuery geoQuery;


            private OnFragmentInteractionListener mListener;

            public OneFragment() {
                // Required empty public constructor
            }

            /**
            * Use this factory method to create a new instance of
            * this fragment using the provided parameters.
            *
            * @param param1 Parameter 1.
            * @param param2 Parameter 2.
            * @return A new instance of fragment OneFragment.
            */
            // TODO: Rename and change types and number of parameters
            public static OneFragment newInstance(String param1, String param2) {
                OneFragment fragment = new OneFragment();
                Bundle args = new Bundle();
                args.putString(ARG_PARAM1, param1);
                args.putString(ARG_PARAM2, param2);
                fragment.setArguments(args);
                return fragment;
            }

            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                if (getArguments() != null) {
                    mParam1 = getArguments().getString(ARG_PARAM1);
                    mParam2 = getArguments().getString(ARG_PARAM2);
                }

            }

            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                    Bundle savedInstanceState) {
                // Inflate the layout for this fragment

                if (null != view) {
                    return view;
                }

                view = inflater.inflate(R.layout.fragment_one, container, false);

                recycler = (RecyclerView) view.findViewById(R.id.one_fragment_recycler_view);
                LinearLayoutManager manager = new LinearLayoutManager(getContext());
                recycler.setLayoutManager(manager);
                postList = new ArrayList<>();
                sortedPostList = new ArrayList<>();
                postIdList = new ArrayList<>();
                adapter = new PostAdapter(postList, getContext());
                recycler.setAdapter(adapter);


                CollectionReference postRef = FirebaseFirestore.getInstance().collection("Posts");

                bundle = getArguments();

                listener = new GeoQueryDataEventListener() {

                    @Override
                    public void onDocumentEntered(DocumentSnapshot documentSnapshot, GeoPoint location) {
                        // ...
                        postList.add(documentSnapshot.toObject(Post.class));

                    }

                    @Override
                    public void onDocumentExited(DocumentSnapshot documentSnapshot) {
                        // ...
                    }

                    @Override
                    public void onDocumentMoved(DocumentSnapshot documentSnapshot, GeoPoint location) {
                        // ...
                    }

                    @Override
                    public void onDocumentChanged(DocumentSnapshot documentSnapshot, GeoPoint location) {
                        // ...
                    }

                    @Override
                    public void onGeoQueryReady() {
                        // ...
                        //mergeSortPost(postList, 0, postList.size()-1);
                        adapter.notifyDataSetChanged();
                        Log.d("TAG______", "Damn it did it again");

                    }

                    @Override
                    public void onGeoQueryError(Exception exception) {
                        // ...
                    }
                };

                loadPostList(postRef);


                return view;
            }

            @Override
            public void onAttach(Context context) {
                super.onAttach(context);
                if (context instanceof OnFragmentInteractionListener) {
                    mListener = (OnFragmentInteractionListener) context;
                } else {
                    throw new RuntimeException(context.toString()
                            + " must implement OnFragmentInteractionListener");
                }
            }
            private void removeListener(){
                geoQuery.removeGeoQueryEventListener(listener);
            }


            private void loadPostList(final CollectionReference postRef) {
                GeoFirestore geoFirestore = new GeoFirestore(postRef);

                geoQuery = geoFirestore.queryAtLocation(
                        new GeoPoint(
                                Double.valueOf(bundle.get("latitude").toString()),
                                Double.valueOf(bundle.get("longitude").toString())),
                        Double.valueOf(bundle.get("act_geo_limit").toString())
                );

                geoQuery.addGeoQueryDataEventListener(listener);

            }


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

                removeListener();
            }



            /**
            * This interface must be implemented by activities that contain this
            * fragment to allow an interaction in this fragment to be communicated
            * to the activity and potentially other fragments contained in that
            * activity.
            * <p>
            * See the Android Training lesson <a href=
            * "http://developer.android.com/training/basics/fragments/communicating.html"
            * >Communicating with Other Fragments</a> for more information.
            */
            public interface OnFragmentInteractionListener {
                // TODO: Update argument type and name
                void onFragmentInteraction(Uri uri);
            }


        }
...