My application consists of an ActivityHome using TabLayout
and SectionsPagerAdapter extends FragmentPagerAdapter
to insert placeholder in two internal fragment (FragmentLeft and FragmentRight).
The ActivityHome loads data from the database and passes them through bundle in the two fragment using the method getItem from the SectionsPagerAdapter (pretty much a base SectionsPagerAdapter)
The FragmentRight creates a popup that contains within it another fragment (FragmentPopup). This fragment give at the user the possibility to make change and save all to the database through UPDATE query
This data is displayed in FragmentLeft and FragmentRight, I would like update them when the database is updated via FragmentPopup.
For this I defined a interface in the FragmentPopup (interfaceDataFragmentPopUpToActivity
), that interface is implemented in the HomeActivity. Through this interface the ActivityHome sees that the data has been modified and updates the datas that will then be passed at the two fragment. This update of the datas is performed in ActivityHome with the implementation of the method of my interface.
In addition I have overwritten the notifyDataSetChanged()
method of my SectionsPagerAdapter class for try to update the two fragment.
The problem is that I can not recharge the fragments (I'm interested above all the FragmentLeft) properly.
This is a little part of the code of the MainActivity
public class ActivityHome extends AppCompatActivity InterfaceDataFragmentPopUpToActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
private Bundle bundle;
private FragmentLeft fragmentLeft;
private FragmentRight fragmentRight;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// Set up the ViewPager with the sections adapter.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
...
}
//method from my interface
@Override
public void updateData(Boolean changeData) {
if (changeData) {
...
Load data from database;
...
bundle = new Bundle();
bundle.putParcelable("dataPass", dataPass);
mViewPager.getAdapter().notifyDataSetChanged();
}
}
//My SectionsPagerAdapter inside the java file of the ActivityHome
public class SectionsPagerAdapter extends FragmentPagerAdapter {
private Bundle bundleAdapter;
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
public SectionsPagerAdapter(FragmentManager fm, Bundle bundleAdapter) {
super(fm);
this.bundleAdapter = bundleAdapter;
}
//this is one of the latest tests carried out to update the Fragment
@Override
public void notifyDataSetChanged(){
this.bundleAdapter = bundle;
fragmentLeft = new FragmentLeft();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
fragmentLeft.setArguments(bundle);
ft.replace(R.id.your_placeholder, fragmentLeft);
ft.commit();
}
@Override
public Fragment getItem(int position) {
fragmentLeft = new FragmentLeft();
fragmentRight = new FragmentRight();
fragmentLeft.setArguments(bundleAdapter);
fragmentRight.setArguments(bundleAdapter);
switch (position) {
case 0:
return fragmentLeft;
case 1:
return fragmentRight;
default:
return fragmentLeft;
}
}
@Override
public int getCount() {
// Show 2 total pages.
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
// Replace blank spaces with image icon
SpannableString sb = new SpannableString(tabTitles[position]);
return sb;
}
}
The ActivityHome layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<FrameLayout
android:id="@+id/your_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"></FrameLayout>
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="@menu/activity_home_drawer" />
</android.support.v4.widget.DrawerLayout>
SOLVED
i have find the solution in this post Remove Fragment Page from ViewPager in Android
I have change FragmentPageAdapter
with `FragmentStatePageAdapater
and Override this method:
@Override
public int getItemPosition(Object object) {
//FragmentLeft is the class for the first fragment in the view
//recreate only FragmentLeft
if (object instanceof FragmentLeft) {
return POSITION_NONE;
}
return 1;
}
I propose again the explanation
Why this solution works
Overriding getItemPosition():
When notifyDataSetChanged()
is called, the adapter calls the notifyChanged()
method of the ViewPager
which it is attached to. The ViewPager
then checks the value returned by the adapter's getItemPosition()
for each item, removing those items which return POSITION_NONE
(see the source code) and then repopulating.