17

私はAndroidのsupport.v4パッケージを使用して、複数のFragmentを含むViewPagerを開発しています。ViewPager時間が経つと破損するフラグメントはありますか?

ユーザーがページを変更したときにビューを非表示にしようとしています。だから、OnPageChangeListenerを実装して私のアダプタを聞いて、Fragmentupdate()メソッドを呼び出すと、ページが変更されたときに呼び出されます。しかし、私はNullPointerExceptionを手に入れています。理由を理解できません。ここで

コードです:私はコピー

public class MyActivity extends FragmentActivity implements 
     OnPageChangeListener { 

    private static final int NUM_ITEMS = 2; 
    private ViewPager mPager; 
    private static SpaceAdapter mAdapter; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.fragment_pager); 

     mAdapter = new SpaceAdapter(getSupportFragmentManager()); 
     mPager = (ViewPager) findViewById(R.id.pager); 
     mPager.setAdapter(mAdapter); 

     mPager.setOnPageChangeListener(this); 
} 

    public static class SpaceAdapter extends FragmentPagerAdapter { 

     public SpaceAdapter(FragmentManager fm) { 
      super(fm); 
     } 

     @Override 
     public int getCount() { 
      return NUM_ITEMS; 
     } 

     @Override 
     public Fragment getItem(int position) { 
      switch (position) { 
      case 0: 
      return new MyFragment(); 
      case 1: 
      return new MyFragment(); 
      default: 
      return new MyFragment(); 
      } 
     } 
    } 

    @Override 
    public void onPageScrollStateChanged(int arg0) { 
     Log.i("pagination", "scroll state changed: " + arg0); 
} 

    @Override 
    public void onPageScrolled(int arg0, float arg1, int arg2) { 
     // Log.i("pagination", "page scroll: " + arg0 + " with: " + arg1 + ", " + arg2); 
     if (mAdapter.getItem(arg0) instanceof IUpdateOnPage) { 
      ((IUpdateOnPage) mAdapter.getItem(arg0)).updateOnPage(); 
     } 
    } 

    @Override 
    public void onPageSelected(int arg0) { 
     Log.i("pagination", "page selected: " + arg0); 
    } 
} 

public class MyFragment extends Fragment implements 
     SurfaceHolder.Callback, IUpdateOnPage { 

    private SurfaceView charts; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     View v = inflater.inflate(R.layout.crew, null); 
     bindViews(v); 
     return v; 
    } 

    private void bindViews(View v) { 
     charts = (SurfaceView) v.findViewById(R.id.civ_charts); 

     charts.getHolder().addCallback(this); 
     Log.i("wtf", "huh " + String.valueOf(charts == null)); // logs false 
    } 

    @Override 
    public void updateOnPage() { 
     if (charts != null) { 
      Log.i("crew surface", "hidden"); 
      charts.setVisibility(View.GONE); 
     } else { 
      Log.i("crew surface", "charts is null"); //THIS HERE gets logged 
     } 
    } 
} 

wWhen /貼り付け私はSurfaceHolder.Callbackメソッドを削除し、彼らはそこにあります。 bindViews(v)メソッドは、charts == nullの場合にログを記録し、常にfalseを返します。私がページすると、updateOnPageが呼び出され、charts == nullがtrueを返します。なぜこれが起こり、どのように私はそれを回避するのですか?

と、これは108行です:あなたのケースでは、あなたのViewPagerを初期化する場合は、次を追加します

charts.setVisibility(View.GONE); 
+0

さらに詳しい調査の後、ページングが始まると(たとえビューが残っていても)フラグメントが破壊されると仮定しています。スワイプすると、私はまだ新しい断片がフルビューになるまで断片の「半分」を見ることができます。したがって、すべての参照が収集され、残っているすべてがビューである場合、どのようにこれを行うことができますか? – edthethird

+0

'NullPointerException'を取得している場合は、logcat出力を投稿できますか? –

+0

私は実際にそれをキャッチしているので、例外はスローされません。問題は 'charts.setVisibility(View.GONE);'です。チャートはnullです。これは 'else'のすぐ上にある2番目のコードサンプルの最後です。スタックトレースを追加しました。 – edthethird

答えて

33

mPager.setOffscreenPageLimit(NUM_ITEMS-1); 

、これは(1にオフスクリーンページ数を設定しますすなわち、他のページが現在焦点を合わせているときに、追加のオフスクリーンページをメモリに保持する)。これにより、Fragmentのすべてがフォーカスされていなくても保持されるように、ViewPagerが強制的に強制されます。

+0

別のマイナーなパフォーマンスの問題を修正しました。ありがとうございました!しかし、このフラグメントが同じヌルポインタで表示されてもクラッシュします。 – edthethird

+0

実際には、コアの問題が修正されています。私はもうsetVisibilty(View.gone)を呼び出す必要はありません。不思議ですが、ありがとう!SurfaceViewが正しくページングされていないことを明確にするために、スワイプしてもすべてのページに残っていました。 – edthethird

+0

v4では 'setOffscreenPageLimit'のデフォルト値は1で(NUM_ITEMS - 1は1になります)、これは奇妙ですが、問題が解決してうれしいです。 – louielouie

4

あなたのコードを調べましたが、問題はonPageScrolledgetItemと呼んでいると思います。この実装(実際にはWeb上のほとんどの実装に似ています)は、毎回新しいインスタンスを返します。しかし、私が見たほとんどの例ではgetItemに電話をかけないので、これは大丈夫です。それは、それを作成し、その位置のために存在し、その後、ArrayListまたはいくつかの他のコレクションにその上にハングアップするが、それは既に存在している場合しない場合:お使いの場合には

、私はgetItemでフラグメントを作成なまけ開催します、そのコレクションから返すだけです。

それ以外の場合は、フラグメントインスタンスAを作成し、別のフラグメントインスタンスBにスクロールします。フラグメントインスタンスAにいくつかのビューをクリーンアップするように指示しますが、新しいフラグメントインスタンスCに指示します。まだ独自のビューを設定する機会はありませんでしたので、チャートへのポインタはnullになります。

+0

ああ、それは良い点です。私はどこかでGoogleのサンプルからこの実装を得ましたが、フラグメントを維持するために配列や何かを実装することを検討します。ありがとう! – edthethird

関連する問題