Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Passing Objects Between Fragments

Before i start, i have look through question such as:

Passing data between fragments: screen overlap How to pass values between Fragments

as well as Android docs:

http://developer.android.com/training/basics/fragments/communicating.html

as well as this article:

http://manishkpr.webheavens.com/android-passing-data-between-fragments/

Though all the cases mentioned above similar to what i have, it is not entirely identical. I followed a good tutorial here (Some portion of my code is based on this article):

http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/

I have the following files:

RegisterActivity.java
NonSwipeableViewPager.java
ScreenSliderAdapter.java
RegisterOneFragment.java
RegisterTwoFragment.java

And the following layouts:

activity_register.xml
fragment_register_one.xml
fragment_register_two.xml

What i am trying to achieve is passing an Serializable object from RegisterFragmentOne to RegisterFragmentTwo.

So far this is what i have done (some codes are omitted):

RegisterActivity.java

public class RegisterActivity extends FragmentActivity
             implements RegisterOneFragment.OnEmailRegisteredListener{

    public static NonSwipeableViewPager viewPager;
    private ScreenSliderAdapter mAdapter;

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

        // Initilization
        mAdapter = new ScreenSliderAdapter(getSupportFragmentManager());
        viewPager = (NonSwipeableViewPager) findViewById(R.id.pager);
        viewPager.setAdapter(mAdapter);
    }

    public void onEmailRegistered(int position, Registration regData){
        Bundle args = new Bundle();
        args.putSerializable("regData", regData);
        viewPager.setCurrentItem(position, true);
    }
}

ScreenSliderAdapter.java

public class ScreenSliderAdapter extends FragmentPagerAdapter{

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

    @Override
    public Fragment getItem(int index) {

        switch (index) {
        case 0:
            return new RegisterOneFragment();
        case 1:
            return new RegisterTwoFragment();
        case 2:
            return new RegisterThreeFragment();
        }

        return null;
    }

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

NonSwipeableViewPager.java (extending ViewPager class, and overrides the following)

@Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
    // Never allow swiping to switch between pages
    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // Never allow swiping to switch between pages
    return false;
}

RegisterOneFragment.java

public class RegisterOneFragment extends Fragment {
    OnEmailRegisteredListener mCallBack;
    public interface OnEmailRegisteredListener {
        /** Called by RegisterOneFragment when an email is registered */
        public void onEmailRegistered(int position, Registration regData);
    }

public void onAttach(Activity activity){
    super.onAttach(activity);

    // This makes sure that the container activity has implemented
    // the callback interface. If not, it throws an exception.
    try {
        mCallBack = (OnEmailRegisteredListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnEmailRegisteredListener");
    }
}

... And some to execute some HTTP request via separate thread...
}

What i am trying to accomplish is that when ever a user pressed a button on RegisterOneFragment, a data will be sent to a server (and returns some validation over JSON). If the returned data is valid, the the application should go to the next fragment which is RegistrationTwoFragment.

I am having some confusion as how to pass objects between fragments, since my Fragments is created using an Adapter. And that Adapter is then attached to my Activity.

Can anyone help me with this? Thx

Edit 1:

I tried to make a shortcut (unfortunately does not work) like so:

In RegisterActivity i created:

public Registration regData;

and in RegisterOneFragment:

/* PLACED ON POST EXECUTE */
((RegisterActivity)getActivity()).regData = regData;

Finally called it in RegisterTwoFragment

Registration regData;
regData = ((RegisterActivity) getActivity()).regData;

It throws a nullPointerExceptions

Edit 2

Just to be clear, RegisterActivty contains multiple fragments. And the only way user can navigate between fragment is by clicking a button. The Activity has no Tab bar.

like image 953
Jeremy Avatar asked Nov 15 '13 09:11

Jeremy


People also ask

How do you pass objects between fragments?

Implements the override methods of Parcelable class. You can use Keyboard shortcut as: put cursor over Parcelable class and tap 'Alt, Enter' then click on Implement methods. This is how you Pass data to another Fragment. You can write this piece of code on the event where you want to replace the fragment.

How can I transfer data from one fragment to another fragment in Android?

So to share a string between fragments you can declare a static String in Activity. Access that string from Fragment A to set the value and Get the string value in fragment B. 2. Both fragments are hosted by different Activities- Then you can use putExtra to pass a string from Fragment A of Activity A to Activity B.

How do you pass data from second fragment to first fragment?

All you have to do is implement the correct type of listener, but the main point is shown. In one fragment activity, call a method and pass a variable to the main activity. From the main activity you can send it to your other fragment activity if you'd like. Save this answer.


2 Answers

It's easy to share objects via implementing Serializable to your custom Object. I wrote a tutorial about this here.

From Fragment One:

android.support.v4.app.FragmentTransaction ft = 
    getActivity().getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
OfficeCategoryFragment frag = new OfficeCategoryFragment();

Bundle bundles = new Bundle();
Division aDivision = divisionList.get(position);

// ensure your object has not null
if (aDivision != null) {
    bundles.putSerializable("aDivision", aDivision);
    Log.e("aDivision", "is valid");
} else {
    Log.e("aDivision", "is null");
}
frag.setArguments(bundles);
ft.replace(android.R.id.content, frag);
ft.addToBackStack(null);
ft.commit();

In Fragment two:

Bundle bundle = getArguments();
Division division= (Division) bundle.getSerializable("aDivision");
Log.e("division TEST", "" + division.getName());
like image 109
Shihab Uddin Avatar answered Sep 21 '22 18:09

Shihab Uddin


I would normally have setters or methods similar to this in the containing activity.

So if I understand correctly, you want the user to access RegistrationOneFragment, then when completed, use this data, validate it, and if valid, pass it along to RegistrationTwoFragment and move the user to this Fragment.

Could you simply call validateJson(regData) in your onEmailRegistered method to handle the validation in your activity, if it succeeds, commit a transaction to RegistrationTwoFragment.

Then all you need are getters and setters in your activity or Fragment to say getRegistrationOneData() in the activity or setData(Registration args) in the fragment as your examples show above.

I don't know of any way to pass the args directly into the Fragment.

like image 40
sturrockad Avatar answered Sep 23 '22 18:09

sturrockad