简体   繁体   中英

What is the correct way to call a method on ViewPager fragments when fragments become visible to user in android

I have a TabLayout that uses a ViewPager to show different fragments in tabs. I want to call a method ( beginGettingData() to be precise) on the fragments when they become visible to user. There are two solutions that I used (and searched about for two days) and the result is I still get exceptions regarding fragment not being attached to the activity.

The first method I used is with fragment's setUserVisibleHint(true) . I did something like this:

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    if (isVisibleToUser) {
        if (shouldGetData) {
            beginGettingData();
        }
    }
}

This approach gave me the activity not attached exception and it is true. since this method is being called before fragment's onCreateView method.

So I thought of a second approach and I used ViewPager 's addOnPageChangeListener and called beginGettingData method in onPageSelected method of the listener like this:

@Override
public void onPageSelected(int position) {
    TabFragment fragment = mAdapter.getItem(position);
    fragment.beginGettingData();
}

This works for me if the activity is started from another activity in my application. For example if my MainActivity uses startActivity to start my TabLayout activity. But the problem occurs when the activity is restarted in anyway. For example when the user presses home button, not come back to the application for a long time (which makes android system to kill the activity), and then return to the activity by opening the application again. Or a more simple example would be when the screen rotates. In these scenarios, the onPageSelected method is called before onCreateView (unlike when the activity is tarted fresh) and then again I get the activity not attached exception .

I know I can check that if the fragment is added to the activity or not, but problem is that for the first time, there will be no data to show the user and thus it is not an option for me to use. I MUST call beginGettingData() somehow when the fragment is shown to the user.

So what do you suggest me to do?

ps: this is my complete code of the activity that hosts the TabLayout and ViewPager

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

        mViewPagerOnChangePagelistener = new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                if (!mDataList.get(position)) {
                    getSupportFragmentManager().executePendingTransactions();
                    TabFragment fragment = mAdapter.getItem(position);
                    fragment.beginGettingData();
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        };

        mViewPager = (ViewPager) findViewById(R.id.files_list_view_pager);
        setupViewpager(mViewPager);
        mViewPager.setOffscreenPageLimit(1);
        mTabLayout = (TabLayout) findViewById(R.id.files_list_tabs);
        mTabLayout.setupWithViewPager(mViewPager);
        mViewPager.addOnPageChangeListener(mViewPagerOnChangePagelistener);

        mViewPager.post(new Runnable() {
            @Override
            public void run() {
                mViewPagerOnChangePagelistener.onPageSelected(mViewPager.getCurrentItem());
            }
        });

    }

    private void setupViewpager(ViewPager viewPager) {
        mAdapter = new ViewPagerAdapter(getSupportFragmentManager());
        MediaFragment videoMediaFragment = new MediaFragment();
        MediaFragment pictureMediaFragment = new MediaFragment();
        Bundle videoMediaBundle = new Bundle();
        Bundle pictureMediaBundle = new Bundle();
        videoMediaBundle.putInt("media_type", MediaHelper.MEIDA_TYPE_VIDEO);
        pictureMediaBundle.putInt("media_type", MediaHelper.MEDIA_TYPE_PHOTO);
        videoMediaFragment.setArguments(videoMediaBundle);
        pictureMediaFragment.setArguments(pictureMediaBundle);
        mAdapter.addFragment(videoMediaFragment, "video");
        mAdapter.addFragment(pictureMediaFragment, "picture");
        viewPager.setAdapter(mAdapter);
    }

    private class ViewPagerAdapter extends FragmentPagerAdapter {

        private final List<TabFragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

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

        @Override
        public TabFragment getItem(int position) {
            return mFragmentList.get(position);
        }

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

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

        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
        }
    }
 @Override
public void setMenuVisibility(final boolean visible) {
    super.setMenuVisibility(visible);
    if (visible) {
        if(getActivity() != null){

        if (shouldGetData) {
            beginGettingData();
        }

        }
    }
}

Try this ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM