【问题标题】:Pass data from fragment to activity and then to another fragment将数据从片段传递到活动,然后再传递到另一个片段
【发布时间】:2016-04-07 17:23:54
【问题描述】:

我是碎片通信的新手,所以我真的需要你的帮助。我有一个片段活动和两个片段。

在我的 Fragment A 中,我有一个 edittext(默认值为 null),用户必须在其中输入一个数字。因此,为了捕获输入值,我使用了 addTextChangedListener。在捕获edittext 的新值之后,Fragment A 必须将该值(字符串)传递给容器活动,并且该活动现在已经接收到该值(字符串)。现在这个活动必须将值(字符串)传递给 Fragment B

到目前为止,这是我尝试过的

FragmentActivity:

  public String strDocNum;

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

片段 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;
}

片段 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);
    }


}

到目前为止,我成功地将数据从 Fragment A 传递到 Activity。但是从 Activity 到 Fragment B 它传递了默认值为 null,因此我的 logcat 抛出 NullPointerException。有任何想法吗?我真的迷路了。您的帮助将真正受到我的赞赏。谢谢。

【问题讨论】:

    标签: android android-fragments android-fragmentactivity


    【解决方案1】:

    如果您的要求是将值从一个片段传递到另一个片段,请尝试使用 bundle

    例如:

    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);
    

    这是您的 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;
        }
    
    }
    

    【讨论】:

    • 我会把这个放在哪里?
    • 在启动新片段时。例如:您需要在单击按钮或单击列表视图时打开新片段。
    • 因为我在一个viewpager上有两个片段,我想知道把这段代码放在哪里
    • 你需要如何打开这个新片段。表示您是否想在单击按钮或列表视图时打开新片段。告诉我。
    • 当我打开片段活动时,这两个片段也会打开。
    【解决方案2】:

    建议你看看这篇文章:http://www.vogella.com/articles/AndroidFragments/article.html

    它解释了如何使用侦听器模式将数据从片段传递到活动,以及如何将数据从活动传递到另一个片段。

    根据您的描述和本文,您的代码应如下所示:

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

    【讨论】:

    • 谢谢,但默认值为 null 正在传递给 Fragment B
    • public void onDataPass(String data)调用时为空?
    • 是的,如果我没有在我的编辑文本上放置数据,则它为空
    • 表示您的论点 String data 为空。因此,您的 FragmentA -> Activity 无法正常工作。我以为你搞定了,所以我回答了 Activity -> FragmentB 部分。
    • 当我在edittext上设置一些值时,null就变成了值
    【解决方案3】:

    试试这个:

    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>
    

    【讨论】:

      【解决方案4】:

      在您的片段中定义一个接口,使您的活动实现该接口,并从您的片段中调用这些接口方法以将数据传递给活动。

      从 Activity 调用片段的公共方法以将数据传递给该片段。

      两个片段不应该直接通信。

      这里有详细解释:http://developer.android.com/training/basics/fragments/communicating.html

      【讨论】:

      • 您好,谢谢,但我正在将数据从 Fragment A 传递到 Activity。但是从活动到片段 B 我没有得到用户输入的新值
      【解决方案5】:

      在 Fragment 到 Fragment 之间传输数据的智能方式是通过接口。在这里,Fragments 不能直接相互通信。但是您可以通过 Activity 来实现。这里 Activity 将充当中间人。

      在这种情况下,您需要两个接口。一个接口用于 Activity,另一个接口用于 FragmentB。

      FragmentA 通过 Activity 接口将 EditTextValue 发送给 Activity,Activity 得到这个值后会通过 FragmentB 接口将该值传递给 FragmentB。

      这里是示例代码:

      Activity会实现这个接口:

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

      FragmentB 会实现这个接口:

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

      更改 FragmentA 中的 edittext 值后,它将调用此活动 getValueFromFragmentA 方法。

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

      在得到这个值之后,Activity 会使用下面的方式把这个值传递给 FragmentB—— 之后Activity会在这里获取这个EditText的值

      @Override
      public void getValueFromFragmentA(String value) {
      
          YourFragmentBInstance.getValueFromEditTextInFragmentA(value);
      }
      

      现在这个值将在这个方法中传递给 FragmentB:

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

      完整的源代码和相关答案是我的答案中的here

      谢谢:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多