17

여러 Fragment을 포함하는 ViewPager를 개발하기 위해 안드로이드의 support.v4 패키지를 사용하고 있습니다.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/I는 SurfaceHolder.Callback 방법을 제거 붙여하지만이있다. bindViews(v) 메서드는 charts == null 인 경우 로그를 남기며 항상 false를 반환합니다. 페이지가 열릴 때 updateOnPage이 호출되고 charts == null이 true를 반환합니다. 왜 이런 일이 일어나고 어떻게 해결할 수 있습니까?

이 108 라인 : 귀하의 경우에 당신이 당신의 ViewPager를 초기화 할 때 다음과 같은 추가

charts.setVisibility(View.GONE); 
+0

추가 조사를 마친 후에도 페이지 매김이 시작될 때 조각이 파괴된다고 가정합니다 (보기가 남아 있더라도?). 스 와이프 때 새 조각이 전체보기로 스냅 될 때까지 조각을 "반"볼 수 있습니다. 따라서 모든 참조가 수집되고 왼쪽 모두가 뷰인 경우 어떻게해야합니까? – edthethird

+0

'NullPointerException'을 얻는다면, logcat 출력을 게시 할 수 있습니까? –

+0

잘 예외가 throw되지 않도록 실제로 catch하고 있어요. 문제는'charts.setVisibility (View.GONE);'입니다. 차트가 null입니다. 두 번째 코드 예제의 마지막 부분 인 'else'바로 위에 있습니다. 스택 추적을 추가했습니다. – edthethird

답변

33

,

mPager.setOffscreenPageLimit(NUM_ITEMS-1); 

,이 (1 오프 스크린 페이지의 수를 설정합니다 즉 다른 페이지가 현재 초점에있을 때 추가 오프 스크린 페이지를 메모리에 유지합니다). 이렇게하면 ViewPager에 포커스가없는 경우에도 Fragment을 모두 유지해야합니다.

+0

다른 사소한 성능 문제가 수정되어 감사드립니다. 그러나이 파편이 동일한 널 포인터로 표시 될 때 여전히 충돌합니다. – edthethird

+0

사실, 핵심 문제를 수정합니다. 더 이상 setVisibilty (View.gone)를 호출 할 필요가 없습니다. 이상하지만 감사합니다!명확히하기 위해 - SurfaceView가 제대로 페이징하지 못했습니다. 스 와이프 한 경우에도 모든 페이지에 남아있었습니다. – edthethird

+0

v4에서는'setOffscreenPageLimit'의 기본값은 1이고 (NUM_ITEMS - 1은 1과 같기 때문에) 이상합니다. 그러나 문제가 해결되어 기쁩니다. – louielouie

4

코드를 검사 한 결과 onPageScrolledgetItem이라고 부르는 문제가 있다고 생각합니다. 이 구현 (실제로 웹상의 대부분의 구현과 유사 함)은 매번 새 인스턴스를 반환합니다. 그러나, 내가 본 대부분의 예제는 getItem을 호출하지 않으므로 대개 괜찮습니다.

나는 그 위치에 존재하지 않는 경우 getItem에 조각을 생성하고 생성 한 다음 ArrayList 또는 다른 컬렉션에 걸지 만 이미 존재하는 경우 , 그냥 그 컬렉션에서 그것을 반환합니다.

그렇지 않으면 조각 인스턴스 A를 만든 다음 다른 조각 인스턴스 B로 스크롤합니다. 조각 인스턴스 A에 일부보기를 정리하려고했지만 새 조각 인스턴스 C에이를 알리려고합니다. 자신의 뷰를 아직 설정할 기회가 없으므로 차트에 null 포인터가 생깁니다.

+0

오 그 좋은 지적입니다. 나는 어딘가에 Google 샘플에서이 구현을 가지고 있지만, 배열을 구현하거나 파편을 유지하기 위해 무언가를 조사 할 것이다. 감사! – edthethird

관련 문제