Java 如果我在XML布局中声明了一个片段,我如何将其传递给一个Bundle?
我有一个活动,我用一个片段代替了它。该活动具有一个意图,其中包含关于该活动应该显示哪些数据的一些额外信息 既然我的活动只是一个围绕一个执行相同工作的片段的包装器,那么如果我用XML和标记声明该片段,我如何将该捆绑包放到该片段中呢 如果我使用FragmentTransaction将片段放入一个视图组,我将有机会在片段构造函数中传递此信息,但我想知道片段是在XML中定义的情况 既然我的活动只是一个围绕一个执行相同工作的片段的包装器,那么如果我用XML和标记声明该片段,我如何将该捆绑包放到该片段中呢 你不能Java 如果我在XML布局中声明了一个片段,我如何将其传递给一个Bundle?,java,android,xml,fragment,Java,Android,Xml,Fragment,我有一个活动,我用一个片段代替了它。该活动具有一个意图,其中包含关于该活动应该显示哪些数据的一些额外信息 既然我的活动只是一个围绕一个执行相同工作的片段的包装器,那么如果我用XML和标记声明该片段,我如何将该捆绑包放到该片段中呢 如果我使用FragmentTransaction将片段放入一个视图组,我将有机会在片段构造函数中传递此信息,但我想知道片段是在XML中定义的情况 既然我的活动只是一个围绕一个执行相同工作的片段的包装器,那么如果我用XML和标记声明该片段,我如何将该捆绑包放到该片段中呢
但是,欢迎您在
FragmentManager
上调用findFragmentById()
来检索膨胀后的碎片,然后调用碎片上的某些方法将数据与之关联。虽然显然这不可能是setArguments()
,但您的片段可以通过一些其他方式(onSaveInstanceState()
,setRetainInstance(true)
,等等)在配置更改之后保留数据本身。我看到的唯一解决方案是不将参数用作数据交换通道。相反,制作片段以从其他地方获取必要的信息。回调以获取适当的活动、查阅临时存储内存、单例对象等
另一个有用的解决方案是使用框架,允许不相关的对象通过中介设计模式交换消息。这不是一种封装方式,但我最终从父活动中“拉”出了包:
Bundle bundle = getActivity().getIntent().getExtras();
另一种选择是不在XML中声明片段。我知道这不是你想要做的。但是,您可以在视图中声明以下简单布局:
<LinearLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
<fragment
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/myFragment"
android:name="com.example.MyFragment"
app:screen_name="@string/screen_a"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
在片段中
if (getArguments() != null) {
int role = getArguments().getInt(Global.INTENT_INT_ROLE); }
这种方法并不像在xml中声明它那样干净和简单,但是我已经转向了它,因为它给了您对片段更多的控制。您不能传递捆绑包(除非您以编程方式而不是通过xml膨胀片段),但您可以通过xml将参数(或者更确切地说是属性)传递给片段
这个过程类似于。
除AndroidStudio(当前)外,在该过程中不为您提供帮助
假设这是使用参数的片段(我将使用kotlin,但它也完全在Java中工作):
你想做这样的事情:
<LinearLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
<fragment
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/myFragment"
android:name="com.example.MyFragment"
app:screen_name="@string/screen_a"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
差不多完成了,您只需要在片段中读取它,因此添加方法:
override fun onInflate(context: Context?, attrs: AttributeSet?, savedInstanceState: Bundle?) {
super.onInflate(context, attrs, savedInstanceState)
if (context != null && attrs != null && screenName == null) {
val ta = context.obtainStyledAttributes(attrs, R.styleable.MyFragment_MembersInjector)
if (ta.hasValue(R.styleable.MyFragment_MembersInjector_screen_name)) {
screenName = ta.getString(R.styleable.MyFragment_MembersInjector_screen_name)
}
ta.recycle()
}
}
等等,片段中的XML属性:)
限制:
- Android Studio(截至目前)不会在布局XML中自动完成此类参数
- 您不能传递
,只能传递可以定义为Android属性的内容Parcelable
onAttachFragment()
在片段onCreateView方法中
Bundle b = getArguments();
if (b != null)
{
Toast.makeText(getBaseContext(), b.getString("msg"), Toast.LENGTH_SHORT).show();
}
当我问这个问题时,我决定走另一条路。但就在今天,我遇到了类似的情况,回到了这个帖子。我想试试看。setArguments解决方案似乎不起作用:10-24 12:48:33.276:E/AndroidRuntime(21417):由以下原因引起:java.lang.IllegalStateException:Fragment已处于活动状态,将尝试仅对该片段调用一个方法。前几天我遇到了相同的IllegalStateException。问题似乎是您需要调用
setContentView()
,以便对片段进行膨胀。但是setContentView()
也将它们附加到活动,这使得调用setArguments()
为时已晚。这不应标记为正确。这是不正确的。根据片段文档(,setArguments()必须在片段附加到活动之前调用。如果可以通过findFragmentById()找到片段那么片段已经被附加。请参阅以获得正确的解决方案。@Neil:我可以理解您困惑的根源。我做了一个小编辑,以澄清setArguments()
调用的时间。请参阅以获取有关如何将数据传递到XML定义的片段的选项。这有点像“然后不要这样做”然而,这种方法对我来说比通过单例对象交换数据的想法更有意义(另一个答案表明)如果singleton对象没有持久化数据库的支持,那么Android可以在后台破坏您的应用程序进程,并尝试稍后从片段参数或捆绑包中重新创建其以前的状态。singleton不会恢复,应用程序状态将丢失,这会导致错误的UX-请尝试使用片段参数或捆绑包来避免这样做ts或通过数据库备份您的单亲。您的答案非常有用!!!!!!!!!Whaaaaaaa!@a.Steenbergen当然,但常见的情况是,如果AGR不存在,请执行一些默认设置;如果它们确实存在,请使用它。试试这个,非常简单,看到@Danielesegato的优秀答案这是我所需要的。非常感谢您。救世主,正是我所需要的我在等你。悬赏你的正确答案,谢谢!
@Override
public void onAttachFragment(Fragment fragment)
{
super.onAttachFragment(fragment);
if (fragment.getId() == R.id.frgBlank)
{
Bundle b = new Bundle();
b.putString("msg", "Message");
fragment.setArguments(b);
}
}
Bundle b = getArguments();
if (b != null)
{
Toast.makeText(getBaseContext(), b.getString("msg"), Toast.LENGTH_SHORT).show();
}