我遇到了一个奇怪的问题。我在一个拥有主机FragmentActivity的应用程序中使用Fragments,我在其中实现了构建Fragments的内部class FragmentPagerAdapater
并将它们放入我的activity的标签中。
在应用程序中,我需要将一个Object从我的Activity传递给Fragments。我不确定这样做的正确方法是什么,所以我即兴创作,并在片段中找到了静态片段newInstance(Object obj)
。此方法只调用默认的Fragment构造函数并设置实例变量以在Fragment中保存Object。
现在在Fragment的createView()
方法中,我使用实例的Object信息来填充布局。这可以在应用程序启动时正常工作,但是当我将屏幕方向从纵向更改为横向(或相反)时,应用程序崩溃。日志指示createView()
中实例对象上的NullPointerException。我觉得我在生命周期中遗漏了一些东西,但我找不到答案。有没有什么特别的做法,我的片段会保存他们的实例变量,无论如何?
这是一个代码示例,可帮助您了解问题所在:
public class MyFragment extends Fragment {
private Object obj;
public static MyFragment newInstance(Object obj) {
MyFragment fragment = new MyFragment();
fragment.setObject(obj);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.layout_fragment, container, false);
MyType res = ((Type) (obj)).getSomething(); // This line causes the crash because obj is null when I switch to another orientation
// I Do something with res to fill rootView
return rootView;
}
private void setObject(Object obj) {
this.obj = obj;
}
}
// In the Activity I simply create the Fragment using
MyFragment fragment = MyFragment.newInstance(myObjectToPass);
感谢您的帮助!
答案 0 :(得分:2)
当方向切换时(当Android决定重新创建Fragment
时),现有的Fragment
将被销毁,然后重新创建。
但是,当Android重新创建Fragment
时,它不会调用您的自定义newInstance()
方法。它使用空的无参数构造函数。
这意味着您的Fragment
不会对您想要的任何自定义Object
具有非空引用,从而导致NPE被抛出。
您需要找到一种方法来传递Object
。如果Object
是简单数据Object
,请考虑通过setArguments()
方法传递其字段或将其序列化。
MyFragment fragment = new MyFragment();
Bundle data = new Bundle();
data.putString ("key_string", "your string here");
fragment.setArguments (data);
您还可以创建一个查询对象活动的interface
。例如:
public class MyFragment extends Fragment {
public interface ObjectProvider
{
public CustomObject getCustomObject();
}
private ObjectProvider provider;
@Override
public void onAttach (Activity activity)
{
super.onAttach(activity);
try{
provider = (ObjectProvider) activity;//get an instance of the ObjectProvider
}
catch (ClassCastException e)
{
e.printStackTrace();
throw new RuntimeException ("This isn't an ObjectProvider.");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.layout_fragment, container, false);
provider.getCustomObject().getSomething();
return rootView;
}
}
然后你的Activity需要实现界面:
public class MainActivity implements MyFragment.ObjectProvider{
@Override
public CustomObject getCustomObject()
{
return new CustomObject();
}
}
答案 1 :(得分:1)
您也可以使用setRetainInstance(true),如下所示:
public static MyFragment newInstance(Object obj) {
MyFragment fragment = new MyFragment();
fragment.setObject(obj);
fragment.setRetainInstance(true);
return fragment;
}
这将使您的对象在方向更改中保持不变,只需确保该对象没有对活动上下文的引用,否则您将发生内存泄漏。