Search code examples
androidandroid-fragmentsandroid-viewpager

Viewpager Activity in my app gets relaunched


I am a beginner android developer trying to make an android application. My app has a viewpager with 4 fragments. Now whenever I move from main activity (viewpager activity) to another activity and back, the main activity starts again and viewpager displays first fragment instead of the fragment which was in display by user earlier. I have provided my code below. Please help so that I can fix this issue of viewpager unnecessarily rolling back to first fragment.

public class MainActivity extends AppCompatActivity {

    private static final int RC_SIGN_IN = 123;
    private FirebaseAuth mFirebaseAuth;
    private FirebaseAuth.AuthStateListener mAuthStateListener;
    public String ADMIN_CHANNEL_ID = "ADMIN";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
        final PbFragmentPagerAdapter adapter = new PbFragmentPagerAdapter(getSupportFragmentManager());
        final TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
        mFirebaseAuth = FirebaseAuth.getInstance();
        mAuthStateListener = new FirebaseAuth.AuthStateListener() {
            @Override
            public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                FirebaseUser user = firebaseAuth.getCurrentUser();
                if(user!=null){
                    viewPager.setAdapter(adapter);
                    tabLayout.setupWithViewPager(viewPager);
                    viewPager.setOffscreenPageLimit(4);
                    adapter.fetchFragmentByPosition(viewPager, viewPager.getCurrentItem());

                }
                else{startActivityForResult(
                        AuthUI.getInstance()
                                .createSignInIntentBuilder()
                                .setAvailableProviders(Arrays.asList(
                                        new AuthUI.IdpConfig.EmailBuilder().build(),
                                        new AuthUI.IdpConfig.GoogleBuilder().build()
                                        ))
                                   .setLogo(R.drawable.ic_fui_icon_round)
                                .build(),
                        RC_SIGN_IN);
                }
            }
        };

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Create the NotificationChannel
            CharSequence name = getString(R.string.notifications_admin_channel_name);
            String description = getString(R.string.notifications_admin_channel_description);
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel mChannel = new NotificationChannel(ADMIN_CHANNEL_ID, name, importance);
            mChannel.setDescription(description);
            mChannel.enableLights(true);
            mChannel.setLightColor(R.color.colorPrimaryDark);
            mChannel.enableVibration(true);
            NotificationManager notificationManager = (NotificationManager) getSystemService(
                    NOTIFICATION_SERVICE);
            notificationManager.createNotificationChannel(mChannel);
        }

    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode== RC_SIGN_IN){
            if(resultCode==RESULT_OK){
                Toast.makeText(MainActivity.this, "Signed In Successfully!",Toast.LENGTH_SHORT).show();
            }
                else if (resultCode==RESULT_CANCELED){
                    finish();
                }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.sign_out_menu:
                AuthUI.getInstance().signOut(this);
                return true;
            case R.id.share_menu:
                shareApp();
                return true;
            case R.id.terms_menu:
                openTermsActivity();
                return true;
            case R.id.privacy_menu:
                openPrivacyActivity();
                return true;
            case R.id.about_menu:
                openAboutActivity();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    public void openAboutActivity() {
        Intent intent = new Intent(this, AboutActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(intent);
    }
    public void openTermsActivity() {
        Intent intent = new Intent(this, TermsActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(intent);
    }
    public void openPrivacyActivity() {
        Intent intent = new Intent(this, PrivacyActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(intent);
    }
    public void shareApp() {

        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);
        shareIntent.putExtra(Intent.EXTRA_TEXT,
                "Hi, I would like to recommend the xyz app to you..);
        shareIntent.setType("text/plain");
        startActivity(shareIntent);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mFirebaseAuth.removeAuthStateListener(mAuthStateListener);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mFirebaseAuth.addAuthStateListener(mAuthStateListener);
    }

    public class PbFragmentPagerAdapter extends SmartFragmentStatePagerAdapter {
        final int PAGE_COUNT = 4;
        private String tabTitles[] = new String[] { "Open Trades", "Past Trades", "Books", "Broker" };


        public PbFragmentPagerAdapter(FragmentManager fm) {
            super(fm);
        }


        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return new OpenTradesFragment();
                case 1:
                    return new PastTradesFragment();
                case 2:
                    return new BooksFragment();
                case 3:
                    return new BrokersFragment();
                default:
                    return null;
            }
        }

        @Override
        public int getCount() {
            return PAGE_COUNT;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return tabTitles[position];
        }

    }

}

// below code is for pager adapter

public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
    // Sparse array to keep track of registered fragments in memory
    private SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

    public SmartFragmentStatePagerAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
    }

    // Register the fragment when the item is instantiated
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }

    // Unregister when the item is inactive
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }

    // Returns the fragment for the position (if instantiated)
    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }

    public Fragment fetchFragmentByPosition(ViewGroup pagerInstance, int position) {
        Fragment existingInstance = registeredFragments.get(position);
        if (existingInstance != null) {
            return existingInstance;
        } else {
            return (Fragment)instantiateItem(pagerInstance, position);
        }
    }
}

sharing XML file below:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerVertical="true"
    android:orientation="vertical"
    android:id="@+id/main_activity_layout"
    tools:context="in.permabull.permabull.MainActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/sliding_tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabSelectedTextColor="@color/colorPrimaryDark"
        app:tabTextColor="@color/colorGrey"
        app:tabPadding="8dp"
        app:tabMode="scrollable">

    </android.support.design.widget.TabLayout>

        <TextView
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/colorLightGrey"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1">

    </android.support.v4.view.ViewPager>



</LinearLayout>

Solution

  • As expected it was a simple problem.. solved it (using onPageSelected) as follows:

    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                            @Override
                            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
                            }
    
                            @Override
                            public void onPageSelected(int position) {
                                tabPosition=position;
                            }
    
                            @Override
                            public void onPageScrollStateChanged(int state) {
    
                            }
    

    where tabPosition is a global int variable that helps to store the fragment(tab) number on which the viewpager is when back/home button is pressed.