17

Estoy usando el paquete support.v4 de Android para desarrollar un ViewPager que contiene múltiples Fragment s.Fragmentos de ViewPager que se destruyen con el tiempo?

Intento ocultar las Vistas cuando el usuario cambia de página. Entonces, implementé un OnPageChangeListener para escuchar mi adaptador, y llamé a un método update() en mi Fragment s cuando ocurre un cambio de página. Pero obtengo un NullPointerException, y no puedo entender por qué.

Aquí está el código:

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

y

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 
     } 
    } 
} 

wCuando copio/pegar Quité los métodos SurfaceHolder.Callback, pero están ahí. El método bindViews(v) registra si charts == null, y eso siempre devuelve falso. Cuando llamo, se llama a updateOnPage, y charts == null devuelve verdadero. ¿Por qué sucede esto y cómo lo soluciono?

y esto es la línea 108:

charts.setVisibility(View.GONE); 
+0

bien, después de una investigación adicional, supongo que el fragmento se destruye cuando comienza la paginación (¿aunque la vista permanezca?). al deslizar, aún puedo ver "la mitad" del fragmento hasta que el nuevo fragmento encaje en la vista completa. Entonces, si todas las referencias se recopilan y todo lo que queda es la vista, ¿cómo puedo hacer esto? – edthethird

+0

si obtiene una 'NullPointerException', ¿puede publicar la salida de logcat? –

+0

Bueno, de hecho estoy atrapándolo así que no se lanza una excepción. El problema es 'charts.setVisibility (View.GONE);'. gráficos es nulo. Está al final de la segunda muestra de código, justo encima del 'else'. Se agregó rastro de pila. – edthethird

Respuesta

33

Añadir lo siguiente cuando usted hace funcionar su ViewPager,

mPager.setOffscreenPageLimit(NUM_ITEMS-1); 

En su caso, esto hará que el número de páginas fuera de la pantalla a 1 (es decir, mantendrá la página adicional fuera de la pantalla en la memoria cuando la otra página esté actualmente enfocada). Esto obligará a su ViewPager a mantener todos los Fragment s incluso cuando no estén enfocados.

+0

que solucionó otro problema de rendimiento menor que estaba teniendo así que ¡gracias! Pero todavía se bloquea cuando este fragmento se muestra con el mismo puntero nulo. – edthethird

+0

en realidad, eso soluciona el problema central. Ya no necesito llamar a setVisibilty (View.gone). Extraño, ¡pero gracias!Solo para aclarar: el SurfaceView no estaba buscando correctamente, permaneció en todas las páginas incluso cuando pasé. – edthethird

+0

Eso es extraño porque 'setOffscreenPageLimit' se establece de manera predeterminada en 1 (y NUM_ITEMS - 1 sería igual a 1) en v4, pero me alegro de que se haya resuelto su problema. – louielouie

4

Examiné su código y creo que el problema es que en onPageScrolled, está llamando al getItem. Esta implementación (que en realidad es como la mayoría de las implementaciones de la misma en la web) devuelve una nueva instancia cada vez. Sin embargo, la mayoría de los ejemplos que he visto no llaman al getItem, así que esto generalmente está bien.

En su caso, me gustaría mantener con pereza crear el fragmento en getItem: si no existe para esa posición, a continuación, crear, y luego quedarse con él en una colección ArrayList o algún otro, pero si ya existe , solo regrésalo de esa colección.

De lo contrario, cree una instancia de fragmento A, luego desplácese a otra instancia de fragmento B. Intenta decirle a la instancia de fragmento A que limpie algunas vistas, pero termina diciendo a una nueva instancia de fragmento C que lo haga. Todavía no ha tenido la oportunidad de configurar sus propios puntos de vista, por lo que obtiene el puntero nulo en los gráficos.

+0

oh, ese es un buen punto. Obtuve esta implementación de una muestra de google en alguna parte, pero investigaré la implementación de una matriz o algo para mantener los fragmentos. ¡Gracias! – edthethird

Cuestiones relacionadas