In an android application I'm loading data from a Db into a TableView inside a Fragment. But when I reload the Fragment it displays the previous data. Can I repopulate the Fragment with current data instead of previous data?
In an android application I'm loading data from a Db into a TableView inside a Fragment. But when I reload the Fragment it displays the previous data. Can I repopulate the Fragment with current data instead of previous data?
To refresh the fragment accepted answer will not work on Nougat and above version. To make it work on all os you can do following.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
fragmentManager.beginTransaction().detach(this).commitNow();
fragmentManager.beginTransaction().attach(this).commitNow();
} else {
fragmentManager.beginTransaction().detach(this).attach(this).commit();
}
you can refresh your fragment when it is visible to user, just add this code into your Fragment this will refresh your fragment when it is visible.
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// Refresh your fragment here
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
Log.i("IsRefresh", "Yes");
}
}
You cannot reload the fragment while it is attached to an Activity, where you get "Fragment Already Added" exception.
So the fragment has to be first detached from its activity and then attached. All can be done using the fluent api in one line:
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
Update: This is to incorporate the changes made to API 26 and above:
FragmentTransaction transaction = mActivity.getFragmentManager()
.beginTransaction();
if (Build.VERSION.SDK_INT >= 26) {
transaction.setReorderingAllowed(false);
}
transaction.detach(this).attach
(this).commit();
For more description of the update please see https://stackoverflow.com/a/51327440/4514796
In case you are using Navigation Components
You can use navigate(this_fragment_id) to navigate to this fragment but in a new instance. Also you have to pop the backstack before to remove the actual fragment.
Kotlin
val navController: NavController =
requireActivity().findNavController(R.id.navHostFragment)
navController.run {
popBackStack()
navigate(R.id.this_fragment_id)
}
Java
NavController navController =
requireActivity().findNavController(R.id.navHostFragment);
navController.popBackStack();
navController.navigate(R.id.this_fragment_id);
If you are using NavController, try this (kotlin):
val navController = findNavController()
navController.run {
popBackStack()
navigate(R.id.yourFragment)
}
Here what i did and it worked for me i use firebase and when user is logIn i wanted to refresh current Fragment first you will need to requer context from activity because fragment dont have a way to get context unless you set it from Activity or context here is the code i used and worked in kotlin language i think you could use the same in java class
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
val context = requireActivity()
if (auth.currentUser != null) {
if (isVisibleToUser){
context.supportFragmentManager.beginTransaction().detach(this).attach(this).commit()
}
}
}
getActivity().getSupportFragmentManager().beginTransaction().replace(GeneralInfo.this.getId(), new GeneralInfo()).commit();
GeneralInfo it's my Fragment class GeneralInfo.java
I put it as a method in the fragment class:
public void Reload(){
getActivity().getSupportFragmentManager().beginTransaction().replace(LogActivity.this.getId(), new LogActivity()).commit();
}
Use a ContentProvider and load you data using a 'CursorLoader'. With this architecture your data will be automatically reloaded on database changes. Use third-party frameworks for your ContentProvider - you don't really want to implement it by yourself...
Make use of onResume method... both on the fragment activity and the activity holding the fragment.
For example with TabLayout: just implement OnTabSelectedListener. To reload the page, you may use implement SwipeRefreshLayout.OnRefreshListener i.e. public class YourFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
the onRefresh() method will be @Override from the interface i.e.:
@Override
public void onRefresh() {
loadData();
}
Here's the layout:
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryLighter"
app:tabGravity="fill"
app:tabIndicatorColor="@color/white"
app:tabMode="fixed"
app:tabSelectedTextColor="@color/colorTextPrimary"
app:tabTextColor="@color/colorTextDisable" />
Code in your activity
TabLayout tabLayout = (TabLayout) findViewById(R.id.tablayout); tabLayout.setupWithViewPager(viewPager);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
if (tab.getPosition() == 0) {
yourFragment1.onRefresh();
} else if (tab.getPosition() == 1) {
yourFragment2.onRefresh();
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
// Reload current fragment
Fragment frag = new Order();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.fragment_home, frag).commit();
None of these answers worked for me so I might as well post my solution if anyone still has problems with this. This solution works only if you are using the Navigation component.
Go to your navigation graph and find the fragment you want to refresh. Create an action from that fragment to itself. Now you can call that action inside that fragment like so.
private void refreshFragment(){
// This method refreshes the fragment
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_self);
}
Below code reloads the current fragment onClick of button from Parent Activity.
layoutNews.setOnClickListener(v -> {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, fragNews);
ft.detach(fragNews);
ft.attach(fragNews);
ft.commit();
});
Easiest way
make a public static method containing viewpager.setAdapter
make adapter and viewpager static
public static void refreshFragments(){
viewPager.setAdapter(adapter);
}
call anywhere, any activity, any fragment.
MainActivity.refreshFragments();