Asked  6 Months ago    Answers:  5   Viewed   35 times

I'm using the v4 compatibility ViewPager in Android. My FragmentActivity has a bunch of data which is to be displayed in different ways on different pages in my ViewPager. So far I just have 3 instances of the same ListFragment, but in the future I will have 3 instances of different ListFragments. The ViewPager is on a vertical phone screen, the lists are not side-by-side.

Now a button on the ListFragment starts an separate full-page activity (via the FragmentActivity), which returns and FragmentActivity modifies the data, saves it, then attempts to update all views in its ViewPager. It is here, where I am stuck.

public class ProgressMainActivity extends FragmentActivity
{
    MyAdapter mAdapter;
    ViewPager mPager;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
    ...
        mAdapter = new MyAdapter(getSupportFragmentManager());

        mPager = (ViewPager) findViewById(R.id.viewpager);
        mPager.setAdapter(mAdapter);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        ...
        updateFragments();
        ...
    }
    public void updateFragments()
    {
        //Attempt 1:
        //mAdapter.notifyDataSetChanged();
        //mPager.setAdapter(mAdapter);

        //Attempt 2:
        //HomeListFragment fragment = (HomeListFragment) getSupportFragmentManager().findFragmentById(mAdapter.fragId[0]);
        //fragment.updateDisplay();
    }

    public static class MyAdapter extends FragmentPagerAdapter implements
         TitleProvider
    {
      int[] fragId = {0,0,0,0,0};
      public MyAdapter(FragmentManager fm)
      {
         super(fm);
      }
      @Override
      public String getTitle(int position){
         return titles[position];
      }
      @Override
      public int getCount(){
         return titles.length;
      }

      @Override
      public Fragment getItem(int position)
      {

         Fragment frag = HomeListFragment.newInstance(position);
         //Attempt 2:
         //fragId[position] = frag.getId();
         return frag;
      }

      @Override
      public int getItemPosition(Object object) {
         return POSITION_NONE; //To make notifyDataSetChanged() do something
     }
   }

    public class HomeListFragment extends ListFragment
    {
    ...
        public static HomeListFragment newInstance(int num)
        {
            HomeListFragment f = new HomeListFragment();
            ...
            return f;
        }
   ...

Now as you can see, my first attempt was to notifyDataSetChanged on the entire FragmentPagerAdapter, and this showed to update the data sometimes, but others I got an IllegalStateException: Can not perform this action after onSaveInstanceState.

My second attempt involed trying to call an update function in my ListFragment, but getId in getItem returned 0. As per the docs I tried by

acquiring a reference to the Fragment from FragmentManager, using findFragmentById() or findFragmentByTag()

but I don't know the tag or id of my Fragments! I have an android:id="@+id/viewpager" for ViewPager, and a android:id="@android:id/list" for my ListView in the ListFragment layout, but I don't think these are useful.

So, how can I either: a) update the entire ViewPager safely in one go (ideally returning the user to the page he was on before) - it is ok that the user see the view change. Or preferably, b) call a function in each affected ListFragment to update the ListView manually.

Any help would be gratefully accepted!

 Answers

81

Try to record the tag each time a Fragement is instantiated.

public class MPagerAdapter extends FragmentPagerAdapter {
    private Map<Integer, String> mFragmentTags;
    private FragmentManager mFragmentManager;

    public MPagerAdapter(FragmentManager fm) {
        super(fm);
        mFragmentManager = fm;
        mFragmentTags = new HashMap<Integer, String>();
    }

    @Override
    public int getCount() {
        return 10;
    }

    @Override
    public Fragment getItem(int position) {
        return Fragment.instantiate(mContext, AFragment.class.getName(), null);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object obj = super.instantiateItem(container, position);
        if (obj instanceof Fragment) {
            // record the fragment tag here.
            Fragment f = (Fragment) obj;
            String tag = f.getTag();
            mFragmentTags.put(position, tag);
        }
        return obj;
    }

    public Fragment getFragment(int position) {
        String tag = mFragmentTags.get(position);
        if (tag == null)
            return null;
        return mFragmentManager.findFragmentByTag(tag);
    }
}
Tuesday, June 1, 2021
 
barden
answered 6 Months ago
45

I think this is because you are adding your ViewPager directly via the WindowManager. Doing so means that it won't be part of the normal Activity view hierarchy (i.e. a child of the decor view). Activity.findViewById (which traverses views using the decor view as the root) won't be able to locate your ViewPager.

The ViewPager adapter creates Fragments and uses the ViewPager (id) as the container. When creating a Fragment, Android looks for this container via Activity.findViewById, but won't be able to find it and so throws this exception.

It sounds like you want some kind of view that appears on top of the thumbnail grid. You could just use a properly styled Dialog(Fragment) to achieve this. The specifics of implementing that view would best be posed as a separate question.

Monday, July 5, 2021
 
Fredy
answered 5 Months ago
50

From the MSDN Forums:

If you right-click the TableAdapter in the Dataset Designer and click 'Configure' the TableAdapter Configuration Wizard opens where you can reconfigure the main query that defines the schema of your table. This should leave the additional TableAdapter queries (the additional methods) that were added after initial configuration.

Of course the additional methods will also need to be reconfigured if they reference a column that has been removed from the table on the database, or if any of the column definitions change (for example, if the data type is changed or modified). So if an aditional column was added to the table and it allows Null values the existing methods should still work - just depends on the scope of change to the schema of the table in the database.

Sunday, August 1, 2021
 
Shawson
answered 4 Months ago
44

The overload you're using for the constructor of the ReportDataSource object is expecting the name of the data source in that first parameter. You're not supplying this, you need the DataTable name.

Update your code to this and you should be OK:

ReportDataSource source = new ReportDataSource("DataTable1", dt);
Friday, August 6, 2021
 
benjisail
answered 4 Months ago
54

Attempting to retrieve the loader here is simply the wrong idea, as the purpose is to refresh the data. After doing some digging I found that I can notify more than 1 set of content load in my provider using

getContext().getContentResolver().notifyChange(uri, null);

which notifies it of change and refreshes, all this code can be deleted and replaced with a single line.

Monday, November 15, 2021
 
Dev
answered 2 Weeks ago
Dev
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share