简体   繁体   English

将数据从片段传递到活动,然后传递到另一个片段

[英]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. 在我的Fragment A中 ,我有一个edittext (默认值为null),用户必须在其中输入一个数字。 So to capture the input value, I did this using the addTextChangedListener. 因此,为了捕获输入值,我使用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). 并且,在捕获了edittext的新值之后, 片段A必须将该值(字符串)传递给容器活动,并且此活动现在已接收到该值(字符串)。 Right now this activity has to pass the value (string) to Fragment B . 现在,此活动必须将值(字符串)传递给片段B。

So far this is what I've tried 到目前为止,这是我尝试过的

FragmentActivity: FragmentActivity:

  public String strDocNum;

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

Fragment A: 片段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: 片段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. 到目前为止,我已经成功地将数据从Fragment A传递到Activity。 But from Activity to Fragment B it is passing the default value which is null so my logcat throws a NullPointerException. 但是从Activity到Fragment B,它传递的默认值为null,因此我的logcat抛出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 这是您的BaseContainerFragment.java类,将有助于获得更好的跟踪和其他优点

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 我建议您看一下这篇文章: 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 在这里进行了详细说明: http : //developer.android.com/training/basics/fragments/communicating.html

The smart way of transfer data between Fragment to Fragment is via Interface. 在Fragment之间传输数据的聪明方法是通过接口。 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. 一个接口用于Activity,另一个接口用于FragmentB。

FragmentA send EditTextValue to Activity via Activity Interface, after getting this value Activity will pass that value to FragmentB using FragmentB interface. FragmentA通过Activity接口将EditTextValue发送到Activity,获得此值后Activity将使用FragmentB接口将该值传递给FragmentB。

Here is sample code: 这是示例代码:

Activity will implements this interface: 活动将实现此接口:

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

FragmentB will implements this interface: FragmentB将实现此接口:

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

After changing edittext value in FragmentA it will call this Activities getValueFromFragmentA method. 在FragmentA中更改edittext值之后,它将调用此Activity的getValueFromFragmentA方法。

(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 在获得此值之后,Activity将使用下面的方式将此值传递给FragmentB-之后,Activity将在此处获得此EditText值

@Override
public void getValueFromFragmentA(String value) {

    YourFragmentBInstance.getValueFromEditTextInFragmentA(value);
}

Now this value will pass to FragmentB's in this methods: 现在,此值将通过以下方法传递给FragmentB:

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

Full source code and related answer is here in my Answer. 完整的源代码和相关答案是这里在我的答案。

Thanks :) 谢谢 :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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