I have a viewpager and used fragmentpageradapter, now I have 3 fragments and in every fragment I need to make a http request (i.e, hit a api),
I don't want to hit all the api for 3 fragments at a time instead I require to hit the api only when the respective page is the current item visible.
I have already tried setting offscreenlimit, but it did not help. What else can I try?
viewPager.setOffscreenLimit(0);
This can be easily done by using OnPageChangeListener provided by ViewPager class
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
// communicate with Fragment here
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
First remove the API calls from onCreateView of fragments, then use this event listener to check which page is selected, according to the selected position you can communicate to the fragment to call the required API.
Use this in your Fragment
private boolean hasBeenVisibleOnce = false;
#Override
public void setUserVisibleHint(boolean visible) {
super.setUserVisibleHint(true);
if (this.isVisible()) {
if (visible && !hasBeenVisibleOnce) {
new NetCheck().execute();
hasBeenVisibleOnce= true;
}
}
}
you can use setUserVisibleHint to check if a fragment is visible to the user. You want to add another boolean (called hasBeenVisibleOnce) to determine if the fragment has been visible at least once. This is to prevent the HTTP Request to be fired multiple times
Related
Consider there is an activity with a title. Viewpager fragment is inside the activity. Fragment will be loaded with data from network API.
Now I need to update the activity title after getting the data from API.
Problem:
Since Viewpager is used, it loads the (prev), current, (next) fragments too. So activity is not aware of which title it is for.
Each title is different for each fragment, so I need to update the title only when the user views that fragment.
You need to create object of your Activity, By using this Object you are able to use activity method.
For more detail; visit this link.How to use method from another Class?
Use this with addOnPageChangeListener method of pager, in it you will get your current postion of pager.
In you Activity add the listener on ViewPager:
viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
#Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
}
#Override public void onPageSelected(int position)
{
//You can use switch case too
if (position== 0)
{
//set title
}
else if (position== 1)
{
//set title
}...
}
#Override public void onPageScrollStateChanged(int state)
{
}
});
You can call the Activity method from Fragment by
Make method in Activity public
In fragment use getActivty() -> cast it to corresponding Activity then call this method
If you want to call Activity method only when fragment visible you can try https://stackoverflow.com/a/42019934/5381331
In Activity, you want to get the current visible fragment, you can try https://stackoverflow.com/a/47789367/5381331
Well, I think the title is quite self explanatory. I have a ViewPager in my HomeActivity, the ViewPager contains 5 fragments at the moment.
When one of the fragments is visible by calling ViewPager's onPageScrolled I want to modify some views inside the current displayed fragment according to some conditions in the HomeActiviy.
After some research, it seems like I cannot find a good way to communicate in the direction HomeActivity --> Fragments inside ViewPager.
I have easily solved the communication in the direction Fragments in ViewPager --> HomeActivity using an Interfacebut this trick seems to not be working on the other direction.
I can access each time the current displayed fragment using a method on my FragmentStatePagerAdapter
public Fragment getActiveFragment(int position){
return myFragmentsList.get(position);
}
However, by doing that, I would have to cast each Fragment into its class MyFragment1 MyFragment2 MyFragment3....
Any easy clean way to achieve that?. Here is the relevant portion of the code:
mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (currentStatus == 1){
Fragment activeFrag = mPagerAdapter.getActiveFragment(mPager.getCurrentItem());
//here I would like to modify one of the 5 fragments
}
#Override
public void onPageSelected(int position) {}
#Override
public void onPageScrollStateChanged(int state) {}
});
Define an interface,
interface FragmentListenerInterface {
public void onFragmentSelected();
}
Implement this interface in all of your fragments. change the communication between fragment and viewpager. write a method to return fragmentlistenerinterface instead of fragment.
public FragmentListenerInterface getActiveFragment(int position){
return (FragmentListenerInterface) myFragmentsList.get(position);
}
After this just say, in your code
public void onPageSelected(int position) {
mViewPager.getActiveFragment(position).onFragmentSelected();
}
And implement onFragmentSelected() in every fragment.
I have Nested Fragments [1 main Fragment called "MainFrag" and many child Fragments]
the App can show MainFrag or can show other fragments.
what I want to do is to setCurrentItem of MainFrag's ViewPager every time the user selects to show that MainFrag so I tried to put it at it's onCreateView but this only works for the first time the User Shows MainFrag as if user Selects another fragment and then re-selects MainFrag the seCurrentItem is not working
I also tried to put it inside MainFrag's onResume, It worked as required but it also causes a problem that if the user moved the App to background and then reOpen it viewPager will Scroll and i don't want this
So where Exactly Can I put setCurrentItem ?
mViewPager.setCurrentItem(mCurrentWeekFragmentItemNumber);
Edit: I am using Navigation Menu to Move between 3 main fragments where MainFrag is one of them.
After your mViewPager.setAdapter(adapter); method you can put
mViewPager.setCurrentItem(mCurrentWeekFragmentItemNumber);
After setting adapter to viewpager add setCurrentItem method
mViewPager.setAdapter(adapter);
mViewPager.setCurrentItem(mCurrentWeekFragmentItemNumber);
Try this:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
viewPager.setCurrentItem(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
I have a ViewPager that contains some Fragments.
I need to update the title on the Activity Toolbar when the fragment changes.
In which lifecycle method of the Fragment should I call the Activity to set the new title?
It would be nice to use setUserVisibleHint(true), but sometimes it gets called when the Activity is not actually ready (Toolbar is null).
And additionally I need to manage the config change and need to makes sure that the title in the Toolbar is the one of the Fragment currently displayed.
Thanks
I think the better option is do that in onPageSelected()
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
I'm using a FragmentStatePageAdapter (android.support.v4) and I have setOffscreenPageLimit set to 2, so it creates and stores Fragments 2 ahead and 2 behind of the currently displayed Fragment.
Problem:
When the off-screen Fragments are created, they are also immediately started and resumed even though they haven't been painted to the screen yet. (!)
When the current page is changed and the corresponding Fragment is swiped off screen, it isn't paused or stopped. (!)
I've tried logging the behavior of all the callbacks in FSPA and its super class - setPrimaryItem comes the closest to being usable but appears to be called for all sorts of reasons, not just when the fragment is displayed.
How can you detect that one of your Fragments is no longer displayed, or returning to the display?
You could use a listener.
mPager.setOnPageChangeListener(new OnPageChangeListener(){
#Override
public void onPageScrollStateChanged(int arg0) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageSelected(int position) {
if(mPageSelectedListener!=null){
mPageSelectedListener.pageSelected(position);
}
}
});
Where PageSelectedListener is defined by you like so
public interface PageSelectedListener{
public void pageSelected(int position);
};
public void setPageSelectedListener(PageSelectedListener l){
mPageSelectedListener = l;
}
And use it like this in your fragment
if(getActivity() instanceof MyActivity
((MyActivity)getActivity()).setPageSelectedListener(new PageSelectedListener(){
#Override
public void pageSelected(int position) {
if(position==MyAdapter.MY_PAGE){
// do something with currently viewed page...like resume it
} else {
// do something with any other page..like pause it
}
}
});
}