0

I am working with a ViewPager and I have three fragments Fragment A, Fragment B and Fragment C in which Fragment A and Fragment B are to communicate Fragment C. I have implemented the communication logic but here's the thing: I cannot refresh/update the view of Fragment C when data is passed from Fragment B. Everything works fine when Fragment A and Fragment C are to communicate: the views are updated according to the data passed.

Fragment C here is a MediaPlayer ... It plays the media url communicated from Fragment B, but there is change in the layout. Can someone please tell me what's going on here. Here's what I have done till now:

Interface

public interface MediaInterface {
    public void onPodCastClick(int position,
            ArrayList<HashMap<String, String>> toPass);
}

In both the Fragment A and B

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    // TODO Auto-generated method stub
    String title = data.get(position).get("Title").toString();
    SM.setCurrentPlayedID(title);
    popPass.onPodCastClick(position, data);
}

@Override
public void onAttach(Activity activity) {
    // TODO Auto-generated method stub
    super.onAttach(activity);
    try{
        popPass = (MediaInterface)getActivity();
    } catch(ClassCastException e){
        Log.i(tag, "Activity " + getActivity().getClass().getSimpleName()
                + " does not implement the MediaInterface");
        e.printStackTrace();
    }
}

where popPass is an instance of the MediaInterface.

In the MainActivity (where the ViewPager is implemented)

@Override
public void onPodCastClick(int position,
        ArrayList<HashMap<String, String>> toPass) {
    // TODO Auto-generated method stub
    Bundle element = new Bundle();

    element.putSerializable("toPass", toPass);
    element.putInt("position", position);

    Fragment toGo = new FragmentC();
    toGo.setArguments(element);
    FragmentTransaction transaction = getSupportFragmentManager()
            .beginTransaction();
    transaction.add(toGo, "FragmentC").commit();
    pager.setCurrentItem(FRAGMENT_C);
}

In Fragment C

Bundle element = getActivity().getSupportFragmentManager()
                    .findFragmentByTag("FragmentC").getArguments();

where there are changes made in the views according to the elements in the Bundle.

Please do help me figure out what's happening and how do I refresh this fragment.

I also did see this from the android developers documentation ... but they did not mention a way to update the UI.

Rakeeb Rajbhandari
  • 5,043
  • 6
  • 43
  • 74

2 Answers2

1

ViewPagers create right and (if any)left fragments instances automatically. In your case; C is not updated by B, because it is already added and C's onCreate method is not going to be invoked.
C is going to be updated if you add it from fragment A because you have only A and B fragments, C is going to be created.
for solution do not add your C fragment if it exists, get C fragment and just update it(use find fragmentByTag).

Devrim
  • 15,345
  • 4
  • 66
  • 74
  • thank you for the explanation. made a lot of things clear. but how do I update C like that ? – Rakeeb Rajbhandari Oct 24 '13 at 16:49
  • You can declare a property on your activity, such as mediaPosition. Update it from fragment A and B when a click occurs with a method. Then write your logic on your activity: if fragment C is found just set its media position to mediaPosition and then invoke pagers setCurrentItem. On resume of your fragment C play your media.If C is not found pass media position to fragment C and add C. On resume it can play your media. – Devrim Oct 24 '13 at 16:58
  • Or remove your fragment C when your currentItem on pager becomes A or B. And don't change your current logic. – Devrim Oct 24 '13 at 17:13
  • how do i remove fragment C ?? and how do i check if my currentItem is A or B ... sorry I am very new in fragments and viewpagers. – Rakeeb Rajbhandari Oct 24 '13 at 17:17
  • is there any example i could refer to ... i'd be most happy to see that :) – Rakeeb Rajbhandari Oct 24 '13 at 17:32
  • There are many samples,you can google it. Firstly you may search for listening position changes on viewPager: see OnPageChangedListener. Then read the google's docs for fragments to remove them. You can reach and learn these in 5 min;) – Devrim Oct 24 '13 at 17:39
  • On this thread you can see how to remove your fragment from a viewPager: http://stackoverflow.com/questions/10396321/remove-fragment-page-from-viewpager-in-android but I recommend you to update it as I mentioned before. – Devrim Oct 24 '13 at 18:03
1

If I understood it right, the problem is that when the Fragment B is visible, also Fragment C is already created by the ViewPager in order to enable smooth scrolling between the pages. This means that even if you update your interface in C's onResume, that method gets called already when the Fragment B is created.

To solve this, you can overwrite the setUserVisibleHint method to know when your Fragment actually becomes active:

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if (isVisibleToUser == true) { 
        /* This means your fragment just became the active one.
           You should call a GUI update function here. */
    }
}

Then you need to have a function that checks for new data and updates the interface accordingly.

J.Nieminen
  • 566
  • 5
  • 12
  • the problem here is that I am giving instantiating two separate views in FragmentC's onCreateView ... do I not call the onCreateView at all and put up all the GUI updating code here ?? – Rakeeb Rajbhandari Oct 24 '13 at 16:57
  • The `onCreateView` will be called by the system, you shouldn't call it yourself. But what you can do, is put the code that creates the UI into a separate method, which you then call from both `onCreateView` and from the `setUserVisibleHint` to make sure that your GUI is always there. If the interface is very heavy (if possibly creating it twice is not a good idea) you can add some logic to `setUserVisibleHint` to check if the GUI is already created and just change whatever needs to be changed. – J.Nieminen Oct 24 '13 at 17:05
  • using setUserVisibleHint gives me an AsynTask error on FragmentB ... I have data loading in FragmentB's onCreateView. – Rakeeb Rajbhandari Oct 24 '13 at 17:15
  • Hmm, I read the code you posted again, but don't really see why you add the fragment C separately in the click handler. You can create the fragments already when creating your `FragmentPagerAdapter` and just let `ViewPager` handle the switching between them (call `pager.setCurrentItem` to switch page and in your `FragmentPagerAdapter`'s `getItem` just return the correct Fragment). Then use the `setUserVisibleHint` to know when that specific fragment becomes visible. For the communication, check the documentation again. You can get a reference to the fragments and call their methods directly. – J.Nieminen Oct 24 '13 at 17:31
  • I can't say anything about the AsyncTask error without a code snippet. But try to keep all background loading etc. to the minimum before you get the basics (communication between the fragments and the user interfaces) working without any problems. Use some dummy data at first, and start loading on the background only after everything else works. – J.Nieminen Oct 24 '13 at 17:33