简体   繁体   中英

Pass data from fragment to activity and then to another fragment

I'm brand new to fragment communication so I really need your help. I have a fragment activity and two fragments.

In my Fragment A , I have an edittext (default value is null) where user has to input a number. So to capture the input value, I did this using the addTextChangedListener. And after capturing the new value of edittext, Fragment A has to pass that value (string) to the container activity and this activity has now received the value (string). Right now this activity has to pass the value (string) to Fragment B .

So far this is what I've tried

FragmentActivity:

  public String strDocNum;

  @Override
public void onDataPass(String data) {
    // TODO Auto-generated method stub
    Log.d("Document From", data);
    strDocNum = data;
}

Fragment A:

  OnDataPass dataPasser;

  private void getRecords() {
    // TODO getRecords

    // TODO To call methods from fragment to activity
    ((ReceivingStocks)getActivity()).dbConnect();

    strLastDocumentNumber = ((ReceivingStocks)getActivity()).dbHelper.getLastDocumentNumber();
    Log.d("Doc Num", "" + strLastDocumentNumber);
    etDocumentNumber.setText(strLastDocumentNumber);

    etDocumentFrom.addTextChangedListener(new TextWatcher() {
        @Override
        public void afterTextChanged(Editable s) {
            // TODO afterTextChanged

        }

        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            System.out.println("Before text changed " + new String(s.toString()));
        }

        public void onTextChanged(CharSequence s, int start, int before, int count) {

            System.out.println("Ontext changed " + new String(s.toString()));

            if(s.toString().isEmpty()){

            } else {
                strDocumentFrom = s.toString();
                strTransactionDate = 
                        ((ReceivingStocks)getActivity()).dbHelper.getTransactionDateByDocumentNumber(strDocumentFrom);
                strTotalAmount = 
                        ((ReceivingStocks)getActivity()).dbHelper.getTotalAmountByDocumentNumber(strDocumentFrom);
                strVan = 
                        ((ReceivingStocks)getActivity()).dbHelper.getVanByDocumentNumber(strDocumentFrom);

                etTransactionDate.setText(strTransactionDate);
                etTotalAmount.setText(strTotalAmount);
                Log.d("Van", "" + strVan);
                etVan.setText(strVan);

                // TODO TO PASS DATA FROM FRAGMENT TO ACTIVITY
                dataPasser.onDataPass(strDocumentFrom);

            }

        }     
    });
}


public interface OnDataPass {
    public void onDataPass(String data);
}

public void passData(String data) {
    dataPasser.onDataPass(data);
}

@Override
public void onAttach(Activity a) {
    super.onAttach(a);
    dataPasser = (OnDataPass) a;
}

Fragment B:

   private void getRecords() {
    // TODO getRecords

    // TODO To call methods from fragment to activity
    ((ReceivingStocks)getActivity()).dbConnect();
    String mLabel = ((ReceivingStocks)getActivity()).strDocNum;
    Log.d("Document Number From Header", "" + mLabel);
    strUnitOfMeasure = ((ReceivingStocks)getActivity()).dbHelper.getUnitOfMeasureByDocumentNumber(mLabel);
    strQTY = ((ReceivingStocks)getActivity()).dbHelper.getQTYByDocumentNumber(mLabel);
    strUnitPrice = ((ReceivingStocks)getActivity()).dbHelper.getUnitPriceByDocumentNumber(mLabel);
    strAmount = ((ReceivingStocks)getActivity()).dbHelper.getAmountByDocumentNumber(mLabel);

    try{

        if(mLabel.isEmpty()){

        } else {
            String str = ((ReceivingStocks)getActivity()).dbHelper.getItemCodeByDocumentNumber(mLabel);
            Log.d("Item Code", "" + str);
            etItemCode.setText(str);
            etUnitOfMeasure.setText(strUnitOfMeasure);
            etQuantity.setText(strQTY);
            etUnitPrice.setText(strUnitPrice);
            etAmount.setText(strAmount);
        } 


    } catch(SQLiteException e){
        Log.d("Error", "" + e);
    }


}

So far, I am successful at passing data from Fragment A to Activity. But from Activity to Fragment B it is passing the default value which is null so my logcat throws a NullPointerException. Any ideas? I really am lost. Your help will truly be appreciated by me. Thanks.

If your requirement is to pass value from one fragment to another then try using bundle

For ex:

TalkDetail fragment = new TalkDetail();
                        Bundle bundle = new Bundle();

                        bundle.putString("title", title);
                        bundle.putString("largeimg", largeimg);
                        bundle.putString("excert", excert);
                        bundle.putString("description",description);
                        bundle.putString("cat", cat);
                        bundle.putString("header_title", "Talk");
                        //bundle.putInt("postid", postid);

                        fragment.setArguments(bundle);
                        ((BaseContainerFragment)getParentFragment()).replaceFragment(fragment, true);

Here's your BaseContainerFragment.java class that will help to get better back track and other good stuff

public class BaseContainerFragment extends Fragment {

    public void replaceFragment(Fragment fragment, boolean addToBackStack) {
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        if (addToBackStack) {
            transaction.addToBackStack(null);
        }
        transaction.replace(R.id.container_framelayout, fragment);
        transaction.commit();
        getChildFragmentManager().executePendingTransactions();
    }

    public boolean popFragment() {
        Log.e("test", "pop fragment: " + getChildFragmentManager().getBackStackEntryCount());
        boolean isPop = false;
        if (getChildFragmentManager().getBackStackEntryCount() > 0) {
            isPop = true;
            getChildFragmentManager().popBackStack();
        }
        return isPop;
    }

}

I suggest you to take a look on this article: http://www.vogella.com/articles/AndroidFragments/article.html

It explains how to pass data from fragment to activity using Listener pattern and how to pass data from activity to another fragment.

Based on your description and this article your code should look something like this:

FragmentB fragment = (FragmentB) getFragmentManager().findFragmentById(R.id.fragmentb);
if (fragment != null && fragment.isInLayout()) {
    fragment.passData(data);
} 

Try this :

public class FragmentA extends Fragment{
private Callbacks mCallbacks = sCallbacks;

public interface Callbacks {
    public void onSelected();//Add arguments if you wants
}

private static Callbacks sCallbacks = new Callbacks() {
    @Override
    public void onSelected() {
    }
};

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.your_fragment_layout,container, false);
    Button btn=(Button)rootView.findViewById(R.id.btn);
    btn.setOnClickListener(new OnClickListenet{
        public void onClick(View v){
            mCallbacks.onSelected()
        }
    });
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    if (!(activity instanceof Callbacks)) {
        throw new IllegalStateException(
                "Activity must implement fragment's callbacks.");
    }

    mCallbacks = (Callbacks) activity;
}

@Override
public void onDetach() {
    super.onDetach();
    mCallbacks = sCallbacks;
}

}

public class YourFragmentActivity extends FragmentActivity 
implements FragmentA.Callbacks{
FragmentB fragB;

    @Override
    public void onSelected() {
    // Handle fragmentA's btn click event here
    // you can call any function of fragmentB using its instance 'fragB'
    }

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_screen);
    FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
    fragB = new FragmentB();
    /* //Pass values to FragmentB
    Bundle arguments = new Bundle();
    arguments.putSString("MyString", "your string comes here");
    fragB.setArguments(arguments); 
    */
    ft.replace(R.id.fragB_container, fragB).commit();
}       

}

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_alignParentLeft="true"
    android:baselineAligned="false" >

     <FrameLayout
        android:id="@+id/fragA_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <FrameLayout
        android:id="@+id/fragB_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />
</LinearLayout>

Define an interface in your fragment, make your activity implement that interface, and call those interface methods from your fragment to pass data to the activity.

Call a fragment's public methods from an activity to pass data to that fragment.

Two fragments should never communicate directly.

It's explained in detail here: http://developer.android.com/training/basics/fragments/communicating.html

The smart way of transfer data between Fragment to Fragment is via Interface. Here Fragments cannot directly communicate with each other. But you can do it via Activity. Here Activity will act as middle man.

In this scenario you need two Interface. One interface for Activity and another for FragmentB.

FragmentA send EditTextValue to Activity via Activity Interface, after getting this value Activity will pass that value to FragmentB using FragmentB interface.

Here is sample code:

Activity will implements this interface:

public interface IActivityTest {
    public void getValueFromFragmentA(String value);
}

FragmentB will implements this interface:

 public interface IFragmentB {
    public void getValueFromEditTextInFragmentA(String value);
    } 

After changing edittext value in FragmentA it will call this Activities getValueFromFragmentA method.

(IActivityTest)getActivity()).getValueFromFragmentA("YOUR_EDITTEXT_NEW_VALUE");

After getting this value Activity will pass this value to FragmentB using bellow way-- After that, Activity will get this EditText value in here

@Override
public void getValueFromFragmentA(String value) {

    YourFragmentBInstance.getValueFromEditTextInFragmentA(value);
}

Now this value will pass to FragmentB's in this methods:

@Override
public void getValueFromEditTextInFragmentA(String value){
 // Here value is your desired value.
}

Full source code and related answer is here in my Answer.

Thanks :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM