1

我有一个奇怪的问题。我在具有主机 FragmentActivity 的应用程序中使用 Fragments,在该应用程序中我实现了class FragmentPagerAdapater构造 Fragment 并将它们放入我的活动选项卡的内部。

在应用程序中,我需要将一个对象从我的 Activity 传递给 Fragments。我不太确定这样做的正确方法是什么,所以我即兴创作,并newInstance(Object obj)在我的片段中选择了一个静态片段。此方法只是调用默认 Fragment 的构造函数并设置一个实例变量以将 Object 保存在 Fragment 中。

现在在 Fragment 的createView()方法中,我使用实例的对象信息来填充布局。这在应用程序启动时工作正常,但是当我将屏幕方向从纵向更改为横向(或相反)时应用程序崩溃。日志表明在 中的实例对象上出现 NullPointerException createView()。我觉得我错过了生命周期中的某些东西,但我找不到答案。有什么特别的事情要做,所以我的 Fragments 无论如何都会保存它们的实例变量?

这是一个代码示例,可帮助您了解问题所在:

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);

谢谢你的帮助 !

4

2 回答 2

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();
 }
} 
于 2013-03-15T16:49:42.283 回答
1

您也可以只使用 setRetainInstance(true) ,如下所示:

public static MyFragment newInstance(Object obj) {
    MyFragment fragment = new MyFragment();
    fragment.setObject(obj);
    fragment.setRetainInstance(true);
    return fragment;
}

这将使您的对象在方向更改时保持不变,只需确保该对象没有对活动上下文的引用,否则您将发生内存泄漏。

于 2013-03-15T17:58:15.010 回答