在实例化时将对象传递给 Fragment 或 DialogFragment
Posted
技术标签:
【中文标题】在实例化时将对象传递给 Fragment 或 DialogFragment【英文标题】:Passing an Object to Fragment or DialogFragment upon Instantiation 【发布时间】:2013-04-30 15:01:55 【问题描述】:我正在尝试找出在不违反“empty constructor”规则的情况下将对象传递给Fragment 或DialogFragment 的正确方法。
例如,我创建了一个自定义视图,并为每个我实例化的视图关联一个 DiaglogFragment。此 DialogFragment 将用于显示控件,用户可以使用这些控件更改与其关联的自定义 View 的某些方面。因为 View 是一个我知道我不能使用 setArguments() 的对象。
我可以实现我的 DialogFragment 的 newInstance(View) 方法,即工厂模式,但是如果我的 Fragment 被系统保存然后在以后恢复会发生什么?据我所知,不会有对 View 对象的引用?
有人能告诉我我是否以错误的方式使用 Fragment,或者是否有办法实现将对象传递给 Fragment,这也将处理系统在以后重建它。
【问题讨论】:
向你的片段添加一个setter,然后在new Fragment()
之后调用那个setter?但是您不想设置视图。您想告诉片段它需要显示什么,并且它应该能够自己提出视图。如果活动正在做这项工作,那么这可能意味着您没有正确拆分片段和活动。
片段不会显示视图,它只是与其密切相关。然而 Fragment 需要将数据传回给 View(比如选择了哪个 Radio 按钮)
正确的做法是创建一个接口,让活动实现并且片段可以调用方法。基本上,活动应该协调活动中片段和其他视图之间的任何交互。
是的,你让我意识到我正在以不应该的方式使用 Fragments。我能做的是传入视图的 id 以及包含该视图的片段。需要时,我的 DialogFragment 可以回调包含 Activity 以传递数据。
【参考方案1】:
在您的 DialogFragmnet
类中,您创建了两个方法:
newInstance
创建您的 DialogFragment
的实例
setter 来初始化你的对象
并在onCreate
中添加setRetainInstance(true);
public class YourDialogFragment extends DialogFragment
ComplexVariable complexVar;
public static YourDialogFragment newInstance(int arg, ComplexVariable complexVar)
YourDialogFragment frag = new MoveSongDialogFragment();
Bundle args = new Bundle();
args.putInt("count", arg);
frag.setArguments(args);
frag.setComplexVariable(complexVar);
return frag;
public void setComplexVariable(ComplexVariable complexVar)
this.complexVar = complexVar;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setRetainInstance(true);
然后,显示对话框
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
Fragment prev = manager.findFragmentByTag("yourTag");
if (prev != null)
ft.remove(prev);
// Create and show the dialog.
DialogFragment newFragment = YourFragmentDialog.newInstance(argument, yourComplexObject);
newFragment.show(ft, "yourTag");
【讨论】:
不确定这是一个好方法,因为您的 DialogFragment 可以自动恢复(例如在旋转期间),然后 yourVar 值将为空。所以DialogFragment在系统自动实例化的情况下会渲染不正确。 似乎将序列化对象放在 Fragment 的 args 中是唯一好的解决方案。或者使用 getActivity()+interface 方法进行标准通信。 @goRGon 你是对的,如果你没有调用片段的 onCreate setRetainInstance(true); 更新了答案并添加了 setRetainInstance(true);供日后参考 或将复杂的变量存储在架构组件 ViewModel 中【参考方案2】:您可以将 Bundle extras 中的 Object 作为 Parcelable Objects (http://developer.android.com/reference/android/os/Parcelable.html ) 传递,并将它们传递给 onCreateView(Bundle savedInstanceState)
中的 Bundle。如果用户翻转屏幕,您可以保存它们。
编辑: this Parcelable 教程相当不错!
另一种方法是从您的 ParentActivity 获取数据对象,但我不确定这是否是一种好方法(但它有效..)
@Override
public void onActivityCreated(Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
mYourObject = ((MainActivity) getActivity()).getYourObject();
您必须为此在 Activity 中创建一个 Getter
public YourObject getYourObject()
return mYourObecjt;
但我认为 Parcelables 是更好的方法,因为您可以在没有任何依赖关系的情况下重用您的 Fragments...
【讨论】:
不确定 Parcelable 是我需要的,但在阅读了链接后,我意识到我可能没有明确我的问题。我需要一个对实际对象的引用。 Parcelable 对象是实际对象的重建/克隆?我需要参考,以便实时更改视图。【参考方案3】:您总是可以使用像 GSON 或 Genson 这样的优秀 JSON 库来序列化对象 - 这是我对任何远程复杂对象的 goto 方法。对于简单的操作,GSON 稍微紧凑一些,但如果您的视图中有任何类型的继承/多态性,我强烈推荐 Genson。只要您记录它们,就可以有一个带参数的 ctr。
https://code.google.com/p/genson/ - 在下载部分获取 JAR。
【讨论】:
感谢您的回复。我意识到我只需要对实际对象的引用,因此任何形式的序列化都会使事情变得复杂。我只需要通过既定方式的活动进行交流。【参考方案4】:我通过 sharepreference 解决了我的需求。 YuzdeDataUser 是我的自定义类,我从我的列表视图中获取它的 onClickItemListener
如何发送
YuzdeDataUser clickedObj = (YuzdeDataUser) parent.getItemAtPosition(position);
//clickedObj.setTarihim();
SharedPreferences shp = getSharedPreferences("sam", MODE_PRIVATE);
SharedPreferences.Editor editor = shp.edit();
Gson gson = new Gson();
String json = gson.toJson(clickedObj);
editor.putString("yoklamaList", json);
editor.commit();
FragmentManager fragmentManager = getSupportFragmentManager();
AylikRaporPop userPopUp = new AylikRaporPop();
userPopUp.show(fragmentManager, "sam");
如何接收
SharedPreferences shp = parent.getSharedPreferences("sam", MODE_PRIVATE);
SharedPreferences.Editor editor = shp.edit();
Gson gson = new Gson();
String json = shp.getString("yoklamaList", "");
YuzdeDataUser user = gson.fromJson(json, YuzdeDataUser.class);
if (user != null)
txt_ad.setText(user.getAd());
txt_tur_tarih.setText(Util.getInstance(parent).writeNameOfTur(user.getTur_id()));
txt_var.setText("" + user.getVar());
txt_gorevli.setText("" + user.getGorevli());
txt_yok.setText("" + user.getYok());
【讨论】:
以上是关于在实例化时将对象传递给 Fragment 或 DialogFragment的主要内容,如果未能解决你的问题,请参考以下文章
Java/Android - 在资源打开的情况下将对象传递给方法