1

I'm trying to make an Android app with a tabbed form. One tab for Autonomous, and the other for TeleOp.

The TeleOp tab needs to be able to read data from the Autonomous tab, but I'm having trouble passing data from one to the other, while I'm switching from the first tab to the next.

They're both fragments, with one parent, called the Match Form. I'm not entirely sure what to do, so here is my code:

MatchForm.java

private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
public TabLayout tabLayout;

public static String startingPos;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_match_form);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.
    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mSectionsPagerAdapter);

    tabLayout = (TabLayout) findViewById(R.id.tabs);

    mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
    tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
    tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_match_form, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";

    public PlaceholderFragment() {
    }

    /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_match_form, container, false);
        TextView textView = (TextView) rootView.findViewById(R.id.section_label);
        textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
        return rootView;
    }
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
 * one of the sections/tabs/pages.
 */
public class SectionsPagerAdapter extends FragmentPagerAdapter {

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

    @Override
    public Fragment getItem(int position) {

        switch(position){
            case 0:
                AutonomousFragment autonomousFragment = new AutonomousFragment();
                return autonomousFragment;
            case 1:
                TeleopFragment teleopFragment = new TeleopFragment();
                return teleopFragment;
        }
        return null;
    }

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

public void easyToast(String text){
    Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}

AutonomousFragment.java

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

    // Make sure that we are currently visible
    if (this.isVisible()) {
        // If we are becoming invisible, then...
        if (!isVisibleToUser) {
            sendData();
        }
    }
}

public void sendData(){
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    TeleopFragment teleopFragment = new TeleopFragment();
    ft.add(R.id.container, teleopFragment);
    final Bundle args = new Bundle();

    args.putString("startingPos", startingPos);
    args.putString("switchPos", switchPos);
    args.putString("scalePos", scalePos);
    args.putString("autoRun", autoRun);
    args.putString("allianceColor", selectedAllianceColor);

    teleopFragment.setArguments(args);
    ft.commit();

}

TeleopFragment.java

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.teleop_fragment, container, false);

    final Bundle bundle = getArguments();

    button = (Button)view.findViewById(R.id.submitButton);
    if(bundle != null && bundle.containsKey("startingPos")){
        startingPos = bundle.getString("startingPos");
        easyToast(startingPos);
    }

    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            easyToast(startingPos);
        }
    });

    return view;
}
anothernode
  • 5,100
  • 13
  • 43
  • 62
  • 3
    Possible duplicate of [How to pass data between fragments](https://stackoverflow.com/questions/5194548/how-to-pass-data-between-fragments) – Aditya Aug 07 '18 at 11:26

3 Answers3

0

You can pass the data from Autonomous Fragment to the parent activity first and then pass it to the Teleop Fragment.

You can use Intents for this.

How to pass values between Fragments

Or use a custom listener to notify the other fragment once the data is sent.

Strauss
  • 737
  • 7
  • 15
0

There are many ways to pass the data.One easy and efficient way to implement.create a public class in your package.In that class declare your values as static.

public class MyDataClass {
public static String value1;
public static String value2;
}

Now you can access these values from anywhere either in the fragment or activity. you can pass the values like this

 MyDataClass myobj=new MyDataClass();
 myobj.value1="Hello";

To fetch the value in another class use

 String val=myobj.value1;
Syed Danish Haider
  • 1,334
  • 11
  • 15
  • Why do the two strings have to be static? – Ismail Hasan Aug 07 '18 at 21:52
  • You can access these static fields from any other class in your application. – Syed Danish Haider Aug 08 '18 at 07:14
  • But couldn't I just make them public, and make an object of the class in another class, and call the two strings like that? – Ismail Hasan Aug 08 '18 at 09:36
  • 1
    @IsmailHasan You probably already found an answer but I'm still going to leave this here for everyone else: No, `value1` and `value2` can't only be public here. Without the `static` keyword they'd behave like normal values, which means that every `MyDataClass` instance you create would have their own 2 values and e.g. "myobj.value1="Hello";` in fragment A wouldn't actually change `myobj.value1` in fragment B (it would still be an empty String). The `static` keyword makes both values exist "outside" and makes sure that when you access `value1`, you always get access to the very same `value1`. – Neph Mar 09 '20 at 12:45
0

1. Do you really need ViewPager here?

ViewPager is needed if you want to display multiple fragments at the same time. On my opinion, the fragments in ViewPager must be equal and independent. If you want to keep communication between Fragments in ViewPager you can:

  1. Use EventBus or LocalBroadcastManager, etc.;
  2. Cache Fragment inside ViewPager in this way

2. Maybe you need flow?

If you want implement some fragment flow, for example "PickGoods" -> "GoodsCheckout", it is better to use fragment transactions and pass arguments with Bundle. For example, pass selected goods ids from "PickGoods" to "GoodsCheckout".

Note. You can't pass really big amount of data. But it is enough for large set of ids.

3. One more solution.

If your flow belongs to separate activity, which is going to be killed, after final action in flow (it is important to avoid memory leaks) you can use ViewModel attached to activity and store data in it. You can get ViewModels attached to activity from its fragments:

ViewModelProviders.of(getActivity()).get(DataViewModel.class);
Ufkoku
  • 2,384
  • 20
  • 44