Reputation: 4124
I have an Activity that has multiple fragments. The fragments all reference the data object in their MasterActivty. The MasterActivtiy may refresh its data.
How do I notify the fragments of data change?
I have tried Broadcasters and other methods, but I'm failing to understand how to do it.
I have looked at these SO questions One, two. but they didn't really make sense for my implementation. I am using a FragmentPagerAdapter
to load the different tabs.
Here is my code:
MasterActivity.java
public class MasterActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_master);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.ic_details));
tabLayout.addTab(tabLayout.newTab().setIcon(R.drawable.ic_notes));
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new TabPagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
refreshData();
}
public void refreshData() {
//do a background task to get data
//WHEN FINISHED TELL FRAGMENTS TO reloadData()
}
}
TabPagerAdapter.java
public class TabPagerAdapter extends FragmentPagerAdapter {
int tabCount;
public TabPagerAdapter(FragmentManager fm, int numberOfTabs) {
super(fm);
this.tabCount = numberOfTabs;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
DetailsFragment tab1 = new DetailsFragment();
return tab1;
case 1:
NotesFragment tab4 = new NotesFragment();
return tab1;
default:
return null;
}
}
@Override
public int getCount() {
return tabCount;
}
}
A fragment
public class DetailsFragment extends Fragment {
private String TAG = getClass().getSimpleName();
public DetailsFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_details, container, false);
viewStatus = (LinearLayout) view.findViewById(R.id.viewStatus);
scrollViewDetails = (LinearLayout) view.findViewById(R.id.scrollViewDetails);
return view;
}
private void reloadData() {
Log.i(TAG, "REALOAD DETAILS FRAGMENT");
//Fill the text views with the data from the MasterActivity
}
}
Upvotes: 0
Views: 39
Reputation: 30985
The way I usually do this is:
Define an interface
public interface DataReloadListener {
void onDataReloaded(Object data); // use your data type here
}
Give the activity the ability to register/unregister the impls (fragments)
Add a data structure to your activity to keep track of listeners:
private List<DataReloadListener> mListeners;
Don't forget to initialize in the constructor:
mListeners = new ArrayList<>();
Add the register/unregister methods to the activity:
public synchronized void registerDataReloadListener(DataReloadListener listener) {
mListeners.add(listener);
}
public synchronized void unregisterDataReloadListener(DataReloadListener listener) {
mListeners.remove(listener);
}
Have the fragment implement the interface and register/unregister for events
@Override
public void onDataReloaded(Object data) {
// update any fragment state here
// if you are updating the UI, check that the fragment currently has a view
if (getView() != null) {
// update UI here
}
}
Override onAttach()
and onDetach()
in the fragments to register/unregister:
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((MasterActivity) activity).registerDataReloadListener(this);
}
@Override
public void onDetach() {
((MasterActivity) getActivity()).unregisterDataReloadListener(this);
super.onDetach();
}
When the event occurs, call onDataReloaded
for all the registered listeners in the activity
public synchronized void onDataReloaded(Object data) {
for (DataReloadListener listener : mListeners) {
listener.onDataReloaded(data);
}
}
All this infrastructure is necessary because your fragment may or may not exist at the time of the event, depending on how the user swipes.
Upvotes: 1