1

私は奇妙な問題を抱えています。class FragmentPagerAdapaterフラグメントを構築してアクティビティのタブに配置する内部を実装したホスト FragmentActivity を持つアプリでフラグメントを使用しています。

アプリでは、オブジェクトをアクティビティからフラグメントに渡す必要があります。これを行う適切な方法がよくわからないので、即興でフラグメントに静的フラグメントnewInstance(Object obj)を使用しました。このメソッドは、デフォルトのフラグメントのコンストラクターを呼び出し、インスタンス変数を設定してフラグメント内のオブジェクトを保持するだけです。

Fragment のcreateView()メソッドでは、インスタンスの Object 情報を使用してレイアウトを埋めます。これはアプリの起動時には問題なく動作しますが、画面の向きを縦から横 (またはその逆) に変更するとアプリがクラッシュします。ログは、 のインスタンス オブジェクトで NullPointerException を示していますcreateView()。ライフサイクルで何かを逃したような気がしますが、答えが見つかりません。私のフラグメントが何があってもインスタンス変数を保存するようにする特別なことはありますか?

問題の内容を理解するのに役立つコード サンプルを次に示します。

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()空の引数なしコンストラクターを使用します。

これは、必要なカスタムへの null 以外の参照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 に答える