如何在Android中从一个片段传输数据到另一个片段

8

我知道的另一种方法是通过接口。我们可以使用接口在片段和活动之间发送数据。


使用接口与托管活动通信,然后将数据从活动传输到片段。 - Raghunandan
不要这样做。 看这个: https://dev59.com/kGYr5IYBdhLWcg3wXJEK - Zyoo
@Zyoo,看看我从文档中直接引用的帖子。 - Raghunandan
是的,我以为这个问题是关于 DialogFragment 回调的。 - Zyoo
@Zyoo 的问题没有提到 DialogFragment,即使有,为什么会是个问题呢? - Raghunandan
显示剩余4条评论
6个回答

15

要将数据从一个片段传递到另一个片段,Bundle会有所帮助。

LifeShapeDetailsFragment fragment = new LifeShapeDetailsFragment(); //  object of next fragment
Bundle bundle = new Bundle();
bundle.putInt("position", id);
 fragment.setArguments(bundle);

然后 推送/调用下一个片段。

跳转到下一个片段的代码:

Bundle bundle = this.getArguments();
int myInt = bundle.getInt("position", 0);

3
根据原始的 Android 开发文档,这种方法是错误的。我们应该使用 Activity 在两个 Fragment 之间进行通信。以下是链接:http://developer.android.com/intl/vi/training/basics/fragments/communicating.html - salih

5

引用自文档:

通常你会希望一个碎片与另一个碎片进行通信,例如根据用户事件更改内容。 所有的Fragment之间的通信都是通过相关联的Activity完成的,两个Fragment不应直接通信。

我建议你按照文档中的方法操作,并且我没有尝试过其他替代方法。

有关更多信息和示例,请查看以下链接中的文档:

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


如果我使用setRetainInstance(true),那么它是否仍然需要传递给活动? - Zyoo
是的,请查看文档http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)。 - Raghunandan

4
有两种方法我认为是可行的:
A. 通过与您所拥有的活动进行通信,并通过该所有活动将消息转发到其他片段,可以在此处找到有关详细信息的官方Android文档:http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity 引用:
在某些情况下,您可能需要一个片段与活动共享事件。一种很好的方式是在片段内定义回调接口并要求主机活动实现它。当活动通过接口接收到回调时,它可以根据需要与布局中的其他片段共享信息。
通信接口可能如下所示:
public interface IActionListener{

  //You can also add parameters to pass along etc
  public void doSomething();
}

该片段会类似于以下内容:
public class MyFragment extends Fragment{

private WeakReference<IActionListener> actionCallback;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            // This makes sure that the container activity has implemented
            // the callback interface. If not, it throws an exception
            actionCallback = new WeakReference<IActionListener>((IActionListener) activity);
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement IActionListener.");
        }
    }
}

我在这里使用了WeakReference,但这真的取决于您。现在,您可以使用actionCallback与拥有的activity进行通信,并调用IActionListener中定义的方法。
拥有者Activity应该长这样:
public class MyActivity extends ActionBarActivity implements IActionListener {

public void doSomething(){ //Here you can forward information to other fragments }

}

B. 至于第二种方法 - 您也可以使用接口直接让片段之间进行通信 - 这样您就不必知道要与哪个片段进行交谈的确切类,从而确保了松散的耦合。

设置如下:您有两个片段(或更多)和一个活动(以启动第二个片段)。我们有一个接口,允许第2个片段在完成任务后向第1个片段发送响应。为简单起见,我们只需重用我在A中定义的接口。

以下是我们的第1个片段:

public class FragmentOne extends Fragment implements IActionListener {

 public void doSomething() {//The response from Fragment 2 will be processed here}

}

使用A中描述的方法,Fragment 1要求其拥有的Activity启动Fragment 2。但是,该Activity将Fragment 1作为参数传递给Fragment 2,因此Fragment 2稍后可以间接访问Fragment 1并发送回复。让我们看看Activity如何准备Fragment 2:

    public class MyActivity extends ActionBarActivity {

    // The number is pretty random, we just need a request code to identify our request later
    public final int REQUEST_CODE = 10;
    //We use this to identify a fragment by tag
    public final String FRAGMENT_TAG = "MyFragmentTag";

        @Override
        public void onStartFragmentTwo() {
            FragmentManager manager = getSupportFragmentManager();
            FragmentTransaction transaction = manager.beginTransaction();

                    // The requesting fragment (you must have originally added Fragment 1 using 
                    //this Tag !)
            Fragment requester = manager.findFragmentByTag(FRAGMENT_TAG);   
                    // Prepare the target fragment
            Fragment target = new FragmentTwo();
                    //Here we set the Fragment 1 as the target fragment of Fragment 2's       
                    //communication endeavors
            target.getSelf().setTargetFragment(requester, REQUEST_CODE);

                    // Hide the requesting fragment, so we can go fullscreen on the target
            transaction.hide(requester);
            transaction.add(R.id.fragment_container, target.getSelf(), FRAGMENT_TAG);
            transaction.addToBackStack(null);

            transaction.commit();
        }
    }

提示: 我正在使用支持框架,因此如果您仅为 > Android 3.0 开发,则可以使用 FragmentActivity 而不是 ActionBarActivity。

现在 FragmentTwo 正在启动,让我们看看 FragmentTwo 如何与 FragmentOne 进行通信:

public class FragmentTwo extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if(savedInstanceState != null){
            // Restore our target fragment that we previously saved in onSaveInstanceState
            setTargetFragment(getActivity().getSupportFragmentManager().getFragment(savedInstanceState, TAG),
                    MyActivity.REQUEST_CODE);           
        }

        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // Retain our callback fragment, the TAG is just a key by which we later access the fragment
        getActivity().getSupportFragmentManager().putFragment(outState, TAG, getTargetFragment());
    }

    public void onSave(){
        //This gets called, when the fragment has done all its work and is ready to send the reply to Fragment 1
        IActionListener callback = (IActionListener) getTargetFragment();
        callback.doSomething();
    }

}

现在将调用 Fragment 1 中 doSomething() 的实现。


我认为你的第一个代码片段中存在代码错误。你在某个地方将你的WeakReference称为“ActionListener”,而在另一个地方称为“ActionCallback”。你能否请检查一下? - Parth Shah
@ParthShah 哦,谢谢!我是凭记忆写的,没有检查变量名 - 再次感谢你,我已经纠正了它。 - AgentKnopf
不过,这个答案非常出色,有很多优秀的例子!干得好! - Parth Shah

3

以下是解决方案:

按照以下步骤进行操作:

1 创建如下所示的接口

     public interface TitleChangeListener
      {
       public void onUpdateTitle(String title);
      }

2. 使用此接口实现您的活动

    for.e.g 
    public class OrderDetail extends ActionBarActivity  implements TitleChangeListener

3. 在这个活动中,在onUpdateTitle()方法中创建。

        public void onUpdateTitle(String title)
        {
         //here orderCompletedDetail is the object second fragment name ,In which fragement I want send data.

         orderCompletedDetail.setTitle(title);
         }

4.现在,在片段一中编写一些代码。

          public class OrderPendingDetail extends Fragment
          {
          private View rootView;
          private Context context;
          private OrderDetail orderDetail;
          @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,    Bundle savedInstanceState)
            {
             rootView = inflater.inflate(R.layout.order_pending_detail, container, false);
            context = rootView.getContext();

            //here OrderDetail is the name of ActionBarActivity 
            orderDetail = (OrderDetail) context;

         //here pass some text to second Fragment using button ClickListener
           but_updateOrder.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) 
               {
                // here call to Activity onUpdateTitle()
                orderDetail.onUpdateTitle("bridal");
                }
        });
        return rootView;
         }
         }

5. 在第二个片段中编写一些代码并设置setTitle()

            public void setTitle(String title)
             {
             TextView orderCompeted_name=(TextView)rootView.findViewById(R.id.textView_orderCompeted_name);
             orderCompeted_name.setText(title);
             //here you see the "bridal" value for TextView
             }

在这个解决方案中,当您单击 Fragment 1 的按钮时,它会在第二个 Fragment 中显示值。 希望对您有所帮助..!!

0

当使用片段时,使用活动作为它们的中介使片段之间相互通信是一种常见的最佳实践。访问http://developer.android.com/guide/components/fragments.html以获取有关此重要模式的更多详细信息。每当您需要与另一个片段交互时,您应始终在片段的活动中使用方法,而不是直接访问其他片段。唯一有意义从一个片段访问另一个片段的时间是当您知道您不需要在另一个活动中重用您的片段时。您几乎总是应该编写片段,假设您将重用它们,而不是将它们硬编码到彼此。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接