1

How can I pass Data from a "Parent" Fragment to a "Child" Fragment?. I already looked how to pass Data between Fragments, but in my case i can not use the Activity.

In my application, I have an Activity which creates a Fragment by clicking on Listitem of the Activity. The Fragment creates a class and the Fragment gets persistent data from the Data-Creating-Class, which is created by a loop. After the creation of the Fragment, it creates several Child-Fragments, each has different Views, which should show the updated data.

But my problem is, that i can not pass the data from the Parentfragment to the Childfragment. I am not sure if its a passing problem or a creating problem of the Childfragment.

In my case the "textValueView" and "mySeries" is always a null. why ?

THE PARENT FRAGMENT

public class ScreenSlidePagerActivity extends Fragment {


    Bundle bundle = new Bundle();

    public boolean stop = false;

    private ServerFragment newServer;

   //Pager Widget for animation handeling
    private ViewPager mPager;

   //Pager Adapter provides the pages to view pager widget
    private PagerAdapter mPagerAdapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                        Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);


        ViewGroup sliderFragmentView = (ViewGroup)   inflater.inflate(R.layout.fragment_screen_slide, container, false);

        ConnectAndReadTask myTask = new ConnectAndReadTask(ScreenSlidePagerActivity.this , "opc.tcp://10.0.2.2:52520" +
            " - " + "mySinus", new NodeId(Integer.parseInt("2"), "mySinus"));
        myTask.execute(new String[]{"opc.tcp://10.0.2.2:52520"});


        // Initiate a ViewPager and a PagerAdapter
        mPager = (ViewPager) sliderFragmentView.findViewById(R.id.pager);
        mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
        mPager.setAdapter(mPagerAdapter);

        return sliderFragmentView;

}

private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {

    public ScreenSlidePagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        switch(position){
            case 0:
                return newServer.newInstance("url","url","url");
            case 1:
                return new GaugeFragment();
            case 2:
                return new GaugeFragment();
            default:
                return new GaugeFragment();
        }

    }

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

@Override
public void onDestroy() {
    stop = true;
    super.onDestroy();
}

/**
 *
 * @param value
 */

public void setData(String value)
{

    Log.d("ScreenSlide.SetData", value);
   // mCallback.onValueSelected(value);#
  bundle.putString("value", value);
    ServerFragment.create(value);
    newServer.setArguments(bundle);
   //newServer.setData(value);

}


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    newServer = new ServerFragment();
}
}

THE CHILDFRAGMENT

public class ServerFragment extends Fragment {

TextView urlTextView, nodeTextView, valueTextView;

public static String passValue;
//Graph
GraphView graphView;
public LineGraphSeries<DataPoint>mySeries;
private double graph2LastXValue = 5d;


public View myFragmentView;
public String url, namespace, nodeName;

public ServerFragment() {}


@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

   myFragmentView  = inflater.inflate(R.layout.fragment_server, container, false);

    urlTextView = (TextView)myFragmentView.findViewById(R.id.urlTextView);
    nodeTextView = (TextView)myFragmentView.findViewById(R.id.nodeTextView);
    valueTextView = (TextView)myFragmentView.findViewById(R.id.valueTextView);



    //Graph
    graphView = (GraphView)myFragmentView.findViewById(R.id.graphView);
    mySeries = new LineGraphSeries<DataPoint>();

    mySeries.setColor(Color.RED);

    graphView.addSeries(mySeries);
    graphView.getViewport().setXAxisBoundsManual(true);
    graphView.getViewport().setMinX(0);
    graphView.getViewport().setMaxX(100);
    graphView.getViewport().setMinY(-20);
    graphView.getViewport().setMaxY(70);

    url = getArguments().getString("url");

    urlTextView.setText(getArguments().getString("url"));
    nodeTextView.setText(getArguments().getString("ns") + " | " + getArguments().getString("nodeName"));

    return myFragmentView;

}



public void setData() {


    Bundle bundle = this.getArguments();

    String value = bundle.getString("value");
    graph2LastXValue += 1d;
    try {
        mySeries.appendData(new DataPoint(graph2LastXValue, Double.parseDouble(value)),
                true, 200);
    }
    catch (Exception e)
    {
        Log.d("mySeries.appendData", e.getMessage());
    }

    try {
        valueTextView.setText(value);
    }

    catch (Exception e)
    {
        Log.d("valueTextView", e.getMessage());
    }




    Log.d("Serverfragment setData:" , value);
}



@Override
public void onStart() {
    super.onStart();

        setData();

}


@Override
public void onDestroy() {

    Log.d("ServerFragment", "disconnected");
    super.onDestroy();
}


@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

}


public static ServerFragment newInstance(String url, String ns, String nodeName) {

    ServerFragment sf = new ServerFragment();
    Bundle b = new Bundle();
    b.putString("url", url);
    b.putString("ns", ns);
    b.putString("nodeName", nodeName);



    sf.setArguments(b);

    return sf;
}

}
royB
  • 12,779
  • 15
  • 58
  • 80
Hasan K
  • 13
  • 1
  • 5

2 Answers2

0

Usual way is to pass it from 1st Fragment to host Activity and it will dispatch it to 2nd Fragment.

I don't know why you can't do that but if it's really like you say you can try to use Otto Bus library by Jake Warton and just subscribe both your fragments to bus.

class Fragment1 { 

  @Override
    public void onResume() {
        super.onResume();
        mBus.register(this);
    }

    @Override
    public void onPause() {
        mBus.unregister(this);
        super.onPause();
    }

    //let's assume you need to do it it on button click
    @Override
    public void onClick(View v) {
      mBus.post(new SomeDataEvent())
    }
} 
//======================

class Fragment2 { 

  @Override
    public void onResume() {
        super.onResume();
        mBus.register(this);
    }

    @Override
    public void onPause() {
        mBus.unregister(this);
        super.onPause();
    }

    //here we define method to handle your data
    @Subscribe
    public void onSomeData(SomeDataEvent object) {
      //do something with it
    }
} 

See more info here http://square.github.io/otto/

Ivan
  • 1,446
  • 2
  • 11
  • 25
0

You can add a public method to your fragments with the data you want as arguments. Then you can call this method from the parent fragment. All you need to do is get the references of the fragments you create.

You can loop through your fragments using mPagerAdapter.getItem(int position);

You can also add identifiers to your fragments as you create them so that you can distinguish them easier. for example instead of new GaugeFragment() you can do new GaugeFragment(identifierString). Now each fragment can tell you information about "who" it is. You can also have different types of fragments.

    PagerAdapter mPagerAdapter;
    ScreenSlidePagerAdapter screenSlidePagerAdapter;

    screenSlidePagerAdapter =  new ScreenSlidePagerAdapter(getFragmentManager());
    mPagerAdapter = screenSlidePagerAdapter;

and later when you want to set your data:

    int count = screenSlidePagerAdapter .getCount();
    for(int i=0;i<count;i++){
        Fragment fragment = screenSlidePagerAdapter .getItem(i);
        if(fragment instanceof GaugeFragment){
            ((GaugeFrament)fragment).gaugeFragmentMethod(data);
            break;
        }
        else if(fragment instanceof OtherTypeOfFragment){
            ((OtherTypeOfFragment)fragment).otherTypeOfFragmentMethod(data);
            break;
        }
    }
Anonymous
  • 4,470
  • 3
  • 36
  • 67
  • I am very thankful for your quick reply. I already have a public method "setData" in my ChildFragment( in this case ServerFragment), which I use for passing the data, but my problem is that I dont have a reference for my ChildFragment. And what do you exactly mean with the method "getItem". The PagerAdapter class dont have this method or am I wrong? – Hasan K Mar 17 '16 at 13:54
  • it's a method of the the FragmentStatePagerAdapter class. Therefore your custom class ScreenSlidePagerAdapter has it too. – Anonymous Mar 17 '16 at 14:35
  • I just saw that you cast ScreenSlidePagerAdapter to PagerAdapter. That's why the method getItem() wasn't available. I updated the answer so now the method should be available – Anonymous Mar 17 '16 at 14:44