Update Fragment from Viewpager

Update Fragment from ViewPager


Update Fragment from ViewPager

You need to implement getItemPosition(Object obj) method.

This method is called when you call

notifyDataSetChanged()

on your ViewPagerAdaper. Implicitly this method returns POSITION_UNCHANGED value that means something like this:
"Fragment is where it should be so don't change anything."

So if you need to update Fragment you can do it with:

  • Always return POSITION_NONE from getItemPosition() method. It which
    means: "Fragment must be always recreated"
  • You can create some update() method that will update your
    Fragment(fragment will handle updates itself)

Example of second approach:

public interface Updateable {
public void update();
}


public class MyFragment extends Fragment implements Updateable {

...

public void update() {
// do your stuff
}
}

And in FragmentPagerAdapter you'll do something like this:

@Override
public int getItemPosition(Object object) {
MyFragment f = (MyFragment ) object;
if (f != null) {
f.update();
}
return super.getItemPosition(object);
}

And if you'll choose first approach it can looks like:

@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}

Note: It's worth to think a about which approach you'll pick up.

How to refresh or update all fragment from the viewpager android

You can use EventBus, put this in all your fragments:

 @Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}

@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}


@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(ViewEvent viewEvent) {
if (viewEvent.getMessage().equals("updateViews")) {
updateView();

}


}

and when you want to update you can send an event like this:

 EventBus.getDefault().post(new ViewEvent("updateViews"));

PS: ViewEvent is an object that you must create with what to send to all suscribed fragments.

public class ViewEvent {

private String message;

public ViewEvent( String message) {

this.message = message;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}
}

Update ViewPager dynamically?

When using FragmentPagerAdapter or FragmentStatePagerAdapter, it is best to deal solely with getItem() and not touch instantiateItem() at all. The instantiateItem()-destroyItem()-isViewFromObject() interface on PagerAdapter is a lower-level interface that FragmentPagerAdapter uses to implement the much simpler getItem() interface.

Before getting into this, I should clarify that

if you want to switch out the actual fragments that are being displayed, you need to avoid FragmentPagerAdapter and use
FragmentStatePagerAdapter.

An earlier version of this answer made the mistake of using FragmentPagerAdapter for its example - that won't work because FragmentPagerAdapter never destroys a fragment after it's been displayed the first time.

I don't recommend the setTag() and findViewWithTag() workaround provided in the post you linked. As you've discovered, using setTag() and findViewWithTag() doesn't work with fragments, so it's not a good match.

The right solution is to override getItemPosition(). When notifyDataSetChanged() is called, ViewPager calls getItemPosition() on all the items in its adapter to see whether they need to be moved to a different position or removed.

By default, getItemPosition() returns POSITION_UNCHANGED, which means, "This object is fine where it is, don't destroy or remove it." Returning POSITION_NONE fixes the problem by instead saying, "This object is no longer an item I'm displaying, remove it." So it has the effect of removing and recreating every single item in your adapter.

This is a completely legitimate fix! This fix makes notifyDataSetChanged behave like a regular Adapter without view recycling. If you implement this fix and performance is satisfactory, you're off to the races. Job done.

If you need better performance, you can use a fancier getItemPosition() implementation. Here's an example for a pager creating fragments off of a list of strings:

ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();

FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
public int getCount() {
return titles.size();
}

public Fragment getItem(int position) {
MyFragment fragment = new MyFragment();
fragment.setTitle(titles.get(position));
return fragment;
}

public int getItemPosition(Object item) {
MyFragment fragment = (MyFragment)item;
String title = fragment.getTitle();
int position = titles.indexOf(title);

if (position >= 0) {
return position;
} else {
return POSITION_NONE;
}
}
});

With this implementation, only fragments displaying new titles will get displayed. Any fragments displaying titles that are still in the list will instead be moved around to their new position in the list, and fragments with titles that are no longer in the list at all will be destroyed.

What if the fragment has not been recreated, but needs to be updated anyway? Updates to a living fragment are best handled by the fragment itself. That's the advantage of having a fragment, after all - it is its own controller. A fragment can add a listener or an observer to another object in onCreate(), and then remove it in onDestroy(), thus managing the updates itself. You don't have to put all the update code inside getItem() like you do in an adapter for a ListView or other AdapterView types.

One last thing - just because FragmentPagerAdapter doesn't destroy a fragment doesn't mean that getItemPosition is completely useless in a FragmentPagerAdapter. You can still use this callback to reorder your fragments in the ViewPager. It will never remove them completely from the FragmentManager, though.

Android ViewPager Refresh fragment

I am sure this is not the only/best way to do it. But this should solve the problem as it did to me.

Please write refresh() methods in both
FragmentCanali and FragmentPreferiti Fragments.

    public class ListCanali extends Fragment implements OnPageChangeListener{
private MyAdapter mAdapter;

@Override
public View OnCreateView (...) {
...
if(mAdapter == null) {
mAdapter = new MyAdapter(getChildFragmentManager());
}
viewPager.setAdapter(mAdapter);
viewPager.setOnPageChangeListener(this);
...
}

...
@Override
public void OnPageSelected (int position) {
switch (position){
case 0 : ((FragmentCanali)adapter.getItem(position)).refresh();
case 1 : ((FragmentPreferiti)adapter.getItem(position)).refresh();
}
}}

It will be cleaner if you extend both the fragments from a base fragment which has abstract refresh() method.

In the onPageSelected() you can just call ((BaseFragment)adapter.getItem(position)).refresh()

Refresh fragment from ViewPager when specifc tab is selected

To correctly encapsulate your Fragment you should not try to refresh it from outside the Fragment.

Viewpager2 and Viewpager with BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT flag set then a Fragment will only be moved to the RESUMED state when it is selected, thus you should put you refresh code in the Fragments onResume method.

As the refresh code is inside the Fragment you don't work out which fragment to refresh.

Kotlin: update fragment in viewPager

Currently, fragmentB is inside fragmentList so you can retrieve it like fragmentList[fragmentBPosition]. Then defind a function inside FragmentB for update the TextView

binding.buttonSend.setOnClickListener {
(fragmentList[1] as FragmentB).updateTheTextView("new")
// if you want code more clean, can replace hard code value by a constant or you can write some logic to find FragmentB from fragmentList
}

FragmentB

class FragmentB : Fragment() {
fun updateTheTextView(newText : String) {
binding.textViewInFragmentB.text = newText
}
}


Related Topics



Leave a reply



Submit