【问题标题】:How to pass a variable from Activity to Fragment, and pass it back?如何将变量从 Activity 传递到 Fragment,并将其传回?
【发布时间】:2013-06-30 10:52:08
【问题描述】:

我目前正在制作一个安卓应用程序,我想在活动和片段之间传递一个日期。 我的活动有一个按钮,可以打开片段:DatePickerFragment。

在我的活动中,我显示了一个日期,我想用片段对其进行修改。所以我想将日期传递给日期选择器,并将其发送回活动。

我尝试了很多解决方案,但都没有奏效。简单的方法是传递一个参数,但这不能用片段来完成。

【问题讨论】:

  • 我的问题和你的一模一样。我想知道为什么这些示例只将片段本身视为日期选择器的“用户”,而不是启动它们的活动。

标签: android android-fragments android-activity


【解决方案1】:

要将信息传递给片段,请在创建片段时设置参数,稍后您可以在片段的 onCreate 或 onCreateView 方法中检索此参数。

在片段的 newInstance 函数上,添加要发送给它的参数:

/**
 * Create a new instance of DetailsFragment, initialized to
 * show the text at 'index'.
 */
public static DetailsFragment newInstance(int index) {
    DetailsFragment f = new DetailsFragment();
    // Supply index input as an argument.
    Bundle args = new Bundle();
    args.putInt("index", index);
    f.setArguments(args);
    return f;
}

然后在方法onCreateonCreateView 的片段内,您可以像这样检索参数:

Bundle args = getArguments();
int index = args.getInt("index", 0);

如果您现在想从片段与您的活动(发送或不发送数据)进行通信,您需要使用接口。您可以执行此操作的方式在片段之间通信的文档教程中得到了很好的解释。因为所有 Fragment 都通过 Activity 相互通信,所以在本教程中,您可以了解如何将数据从实际 Fragment 发送到他的 Activity 容器,以在 Activity 上使用这些数据或将其发送到您的 Activity 包含的另一个 Fragment。

文档教程:

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

【讨论】:

  • 我认为人们一次又一次地问这个问题的意义在于它在文档中没有得到很好的解释。
  • 我仍然对哪种方法最好使用感到困惑,您的方法,还是@Elenasys 回答的以下方法
  • 有一种使用架构组件(I/O '17)在片段之间共享数据的新方法:developer.android.com/topic/libraries/architecture/…
  • 那些在 XML 布局中创建的片段怎么样?
  • 我不想再使用静态方法了。
【解决方案2】:

将数据从Activity 发送到Fragment

活动:

Bundle bundle = new Bundle();
String myMessage = "Stackoverflow is cool!";
bundle.putString("message", myMessage );
FragmentClass fragInfo = new FragmentClass();
fragInfo.setArguments(bundle);
transaction.replace(R.id.fragment_single, fragInfo);
transaction.commit();

片段:

读取片段中的值

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    String myValue = this.getArguments().getString("message");
    ...
    ...
    ...
}

但是如果你想将值从Fragment发送到Activity,阅读jpardogo的答案,你必须需要接口,更多信息:Communicating with other Fragments

【讨论】:

  • 如何传递自定义对象?我使用了Parcelable,但这给了我class cast exception
  • 这个解决方案对我不起作用,找不到从哪里导入交易
  • 好吧,如果您将 Fragment 加载到您的 Activity 中,您可以通过在您的事务中定义的 bundle 发送值。说明你的方案是什么?
  • 我们如何将对象作为包传递?
【解决方案3】:

感谢@ρяσѕρєя K 和 Terry ...这对我有很大帮助并且完美运行

您从 Activity 发送数据的意图如下:

Bundle bundle = new Bundle(); 
bundle.putString("edttext", "From Activity"); 
// set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);

在 Fragment 的 onCreateView 方法中:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // get arguments
    String strtext = getArguments().getString("edttext");    
    return inflater.inflate(R.layout.fragment, container, false);
}

参考: Send data from activity to fragment in android

【讨论】:

    【解决方案4】:

    致所有 Kotlin 开发人员:

    这是 Android Studio 提出的解决方案向您的 Fragment 发送数据(= 当您使用 File -> New -> Fragment -> Fragment(Blank) 创建一个 Blank-Fragment 并检查“包括片段工厂方法”)。

    把它放在你的片段中:

    class MyFragment: Fragment {
    
    ...
    
        companion object {
    
                @JvmStatic
                fun newInstance(isMyBoolean: Boolean) = MyFragment().apply {
                    arguments = Bundle().apply {
                        putBoolean("REPLACE WITH A STRING CONSTANT", isMyBoolean)
                    }
                }
         }
    }
    

    .apply 是一个在创建对象时设置数据的好技巧,或者they state here

    this值作为接收者调用指定函数[block] 并返回this 值。

    然后在您的 Activity 或 Fragment 中执行:

    val fragment = MyFragment.newInstance(false)
    ... // transaction stuff happening here
    

    并阅读片段中的参数,例如:

    private var isMyBoolean = false
    
    override fun onAttach(context: Context?) {
        super.onAttach(context)
        arguments?.getBoolean("REPLACE WITH A STRING CONSTANT")?.let {
            isMyBoolean = it
        }
    }
    

    要将数据“发送”回您的 Activity,只需在 Activity 中定义一个函数并在 Fragment 中执行以下操作:

    (activity as? YourActivityClass)?.callYourFunctionLikeThis(date) // your function will not be called if your Activity is null or is a different Class
    

    享受 Kotlin 的魔力!

    【讨论】:

      【解决方案5】:

      使用库 EventBus 来回传递可能包含您的变量的事件。这是一个很好的解决方案,因为它使您的活动和片段保持松散耦合

      https://github.com/greenrobot/EventBus

      【讨论】:

      • 我不能说这不是一个好的解决方案,但要注意一点。虽然 EventBus 非常易于使用,但它的危险也在这里。如果您开始添加太多信号,松散耦合的性质会使跟踪谁在呼叫谁以及在哪里发生不同事件变得非常困难。
      【解决方案6】:

      将数据从 Activity 发送到由 XML 链接的 Fragments

      如果您使用其中一个模板在 Android Studio 中创建片段,例如文件 > 新建 > 片段 > 片段(列表),然后片段通过 XML 链接。 newInstance 方法在片段中创建,但从未被调用,因此不能用于传递参数。

      而是在Activity中重写onAttachFragment方法

      @Override
      public void onAttachFragment(Fragment fragment) {
          if (fragment instanceof DetailsFragment) {
              Bundle args = new Bundle();
              args.putInt("index", index);
              f.setArguments(args);        
           }
      }
      

      然后根据其他答案读取片段 onCreate 方法中的参数

      【讨论】:

        【解决方案7】:

        现在回答 2021 年的一天片段具有内置的静态方法,这些方法用于 在创建片段时传递参数尝试他们未来的编码器

        当您创建一个片段时,它具有以下已定义的静态方法

         public static categoryfrag newInstance(String param1, String param2) {
                categoryfrag fragment = new categoryfrag();
                Bundle args = new Bundle();
                args.putString(ARG_PARAM1, param1);
                args.putString(ARG_PARAM2, param2);
                fragment.setArguments(args);
                return fragment;
            }
        

        片段中的onCreate方法通过已经定义的代码接收参数

           public void onCreate(Bundle savedInstanceState) {
               super.onCreate(savedInstanceState);
               if (getArguments() != null) {
                   mParam1 = getArguments().getString(ARG_PARAM1);
                   mParam2 = getArguments().getString(ARG_PARAM2);
                 //  rr=getArguments().getInt("ky");
                   sn1=mParam1;
                   sn2=mParam2;
               }
           }
        

        如果您希望其他数据类型修改此内置行或使用 bundle,则在 mostpop 是片段类的名称的活动中使用以下代码

        Fragment mp=mostpop.newInstance("parameter1","parameter2");
        

        【讨论】:

        • 这一切都很好,但你能详细说明一下:至少你的意思是什么方法,最好是简单的代码示例
        【解决方案8】:

        你可以简单地用一个 bundle 实例化你的片段:

        Fragment fragment = Fragment.instantiate(this, RolesTeamsListFragment.class.getName(), bundle);
        

        【讨论】:

          【解决方案9】:

          类中的公共变量声明是最简单的方法:

          关于目标类:

          public class MyFragment extends Fragment {
              public MyCallerFragment caller; // Declare the caller var
          ...
              @Override
              public View onCreateView(LayoutInflater inflater, ViewGroup container,
                     Bundle savedInstanceState) {
                  // Do what you want with the vars
                  caller.str = "I changed your value!";
                  caller.i = 9999;
                  ...
                  return inflater.inflate(R.layout.my_fragment, container, false);
              }
          ...
          }
          

          关于调用者类:

          public class MyCallerFragment extends Fragment {
              public Integer i; // Declared public var
              public String str; // Declared public var
                  ...
                      FragmentManager fragmentManager = getParentFragmentManager();
                      FragmentTransaction transaction = fragmentManager.beginTransaction();
          
                      myFragment = new MyFragment();
                      myFragment.caller = this;
                      transaction.replace(R.id.nav_host_fragment, myFragment)
                              .addToBackStack(null).commit();
                  ...
          }
          

          如果您想使用主要活动,也很容易:

          关于主要活动类:

          public class MainActivity extends AppCompatActivity {
              public String str; // Declare public var
              public EditText myEditText; // You can declare public elements too.
                                          // Taking care that you have it assigned
                                          // correctly.
          ...
          }
          

          关于调用的类:

          public class MyFragment extends Fragment {
              private MainActivity main; // Declare the activity var
          ...
              @Override
              public View onCreateView(LayoutInflater inflater, ViewGroup container,
                     Bundle savedInstanceState) {
                  // Assign the main activity var
                  main = (MainActivity) getActivity();
          
                  // Do what you want with the vars
                  main.str = "I changed your value!";
                  main.myEditText.setText("Wow I can modify the EditText too!");
                  ...
                  return inflater.inflate(R.layout.my_fragment, container, false);
              }
          ...
          }
          

          注意:使用事件(onClick、onChanged 等)时要小心,因为 您可能处于“战斗”状态,其中不止一个分配一个 多变的。结果将是变量有时不会 改变或将神奇地返回到最后一个值。

          更多组合请发挥您的创造力。 :)

          【讨论】:

          • 这将活动和片段紧密耦合在一起,因此限制了片段的可重用性。我们应该找到一种耦合度较低的沟通方式。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多