您的位置:首页 > 其它

Updating a ListView inside a Fragment placed on a ViewPager on DialogFragment dismiss

2014-05-10 06:25 337 查看
Title says all. We’ll see today how to proceed in order to update a ListView that is placed inside a Fragment (not a ListFragment) placed on a ViewPager just after dismissing
aDialogFragment. Seems complicated, huh?


When may we need this?

Well, imagine that you have an Activity which layout uses tabs (represented by Fragments) and you want to use a ViewPager so it feels better to users. With a ViewPager you
can swipe tabs, and that make users happy. Now, think about your Activity’s tabs: you may have three or four and one of them may be a ListView.

Finally, imagine that this ListView is updated every time user inputs data that is stored into a database. The user inputs data using a button that presents a Dialog with buttons or whatever the app needs to show.
When the user pushes the OK button, the Dialog will call onDismiss(). And the ListView should update here, but it won’t do unless you notify it that there are changes.


Nice. How do we do that?

It’s really easy, but it may be confusing sometimes. We will consider that you created a project using Android Studio wizards and that you selected “Tabs+Swipe” navigation option. Take a look at your main Activity, there should be a custom FragmentPagerAdapter.
We’ll make it “remember” your fragments. You can achieve this saving all yourFragments as individual objects or use an array. For example:

1 public class MyPagerAdapter extends FragmentPagerAdapter {
2
3         SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
4
5         ...
6
7         @Override
8         public Fragment getItem(int position) {
9             // getItem is called to instantiate the fragment for the given
10             // page.
11             Fragment fragment = new MyFragment();
12             Bundle args = new Bundle();
13             args.putInt(SectionFragment.ARG_SECTION_NUMBER, position + 1);
14             fragment.setArguments(args);
15             registeredFragments.put(position, fragment);
16             return fragment;
17         }
18
19
20         @Override
21         public void destroyItem(ViewGroup container, int position, Object object) {
22             registeredFragments.remove(position);
23             super.destroyItem(container, position, object);
24         }
25
26         public Fragment getRegisteredFragment(int position) {
27             return registeredFragments.get(position);
28         }
29
30         ...
31
32     }


You just have to override destroyItem() and edit getItem() to handle when we modify the array. Also add getRegisteredFragment() so we can access the fragment array.

Now, on your DialogFragment, declare a new interface and use it on the onDismiss() method. Like this:

1 public class MyDialogFragment extends DialogFragment implements
2 DialogInterface.OnDismissListener{
3
4
5     private OnDBChangedListener mCallback;
6
7     ...
8
9     @Override
10     public void onDismiss(DialogInterface dialog) {
11         mCallback.onDBChanged();
12         super.onDismiss(dialog);
13     }
14
15     // Container Activity must implement this interface
16     public interface OnDBChangedListener {
17         public void onDBChanged();
18     }
19
20     @Override
21     public void onAttach(Activity activity) {
22         super.onAttach(activity);
23
24         // This makes sure that the container activity has implemented
25         // the callback interface. If not, it throws an exception
26         try {
27             mCallback = (OnDBChangedListener) activity;
28         } catch (ClassCastException e) {
29             throw new ClassCastException(activity.toString() + " must implement
30                 OnDBChangedListener");
31         }
32     }
33 }


Call it whatever you want and don’t forget to use onAttach() to be sure that your Activity is acting correctly. For this to happen you have to implement it on your Activity. So, add implements DialogFragmentName.OnDBChangedListener to
your Activity declaration. Also, implement your interface method and use it to call a (yet to write) public method of your ListView fragment.

1 public class MainActivity extends Activity implements ActionBar.TabListener,
2 MyDialogFragment.OnDBChangedListener{
3     ...
4     @Override
5     public void onDBChanged() {
6         SectionFragment sFrag =
7 (SectionFragment)mSectionsPagerAdapter.getRegisteredFragment(1);
8          sFrag.updateDB();
9     }
10 }


Finally, add a public method to your ListView fragment or the Activity will not be able to finish the job : ) Something like this will work if you are using SQLite databases:

1     public void updateDB() {
2         if(dataSource!=null) {
3             ListView lView = (ListView)rootView.findViewById(R.id.listView);
4             dataSource.open();
5
6             List<Foo> foos = dataSource.getAllFoos();
7             adapter = new ArrayAdapter<Foo>(context,
8                     android.R.layout.simple_list_item_1,
9                     foos);
10             lView.setAdapter(adapter);
11             dataSource.close();
12         }
13
14     }


That’s it! Hope it helped someone : )
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息