2012-09-03 5 views
8

나는 ViewPager (extend FragmentPagerAdapter)에 두 개의 Fragments을 보유하고 있습니다. 내가 슬쩍 할 때마다 Fragment에 대해 ListView을 새로 고치면됩니다. 이를 위해 ViewPager.OnPageChangeListener 인터페이스 (즉, onPageScrollStateChanged)를 구현했습니다. Fragment에 대한 참조를 보유하려면 HashTable을 사용합니다. 나는 getItem() 방법 HashTableFragments에 대한 참조를 저장 :FragmentPagerAdapter가 방향 변경시 조각을 다시 생성하지 않습니까?

@Override 
     public Fragment getItem(int num) { 
      if (num == 0) { 
       Fragment itemsListFragment = new ItemsListFragment(); 
       mPageReferenceMap.put(num, itemsListFragment); 
       return itemsListFragment; 
      } else { 
       Fragment favsListFragment = new ItemsFavsListFragment(); 
       mPageReferenceMap.put(num, favsListFragment); 
       return favsListFragment; 
      } 
     } 

내가 다른 하나 Fragment 스 와이프 때 모두 Fragments (새로 고침)에 필요한 메서드를 호출 HashTable를 사용하는 경우 그래서 onPageScrollStateChanged 트리거 :

public void refreshList() { 
     ((ItemsListFragment) mPageReferenceMap.get(0)).refresh(); 
     ((ItemsFavsListFragment) mPageReferenceMap.get(1)).refresh(); 
    } 

orientation change 이벤트가 발생할 때까지 모든 것이 잘됩니다. IllegalStateException

public void refresh() { 
     mAdapter.changeCursor(mDbHelper.getAll()); 
     getListView().setItemChecked(-1, true); // The last row from a exception trace finishes here (my class). 
    } 

결과 :

java.lang.IllegalStateException: Content view not yet created 
     at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328) 
     at android.support.v4.app.ListFragment.getListView(ListFragment.java:222) 
     at ebeletskiy.gmail.com.passwords.ui.ItemsFavsListFragment.refresh(ItemsFavsListFragment.java:17) 

Content보기 제가 trueonActivityCreated() 방법에서 boolean 변수를 설정하고 if/else 사용 실제로 생성되지 가정되는 코드 refresh() 방법에있어서, 후 조건 getListView()으로 전화를 걸면 활동 및 콘텐츠보기가 성공적으로 생성되었음을 알 수 있습니다.

그럼 FragmentPagerAdaptergetItem()을 호출 할 때 디버깅 중이며 orientation change 이벤트 이후에 메소드가 호출되지 않습니다. 따라서 ViewPager에는 이전 Fragments에 대한 참조가 저장됩니다. 이것은 단지 나의 가정입니다.

그럼 ViewPager을 다시 getItem()으로 호출 할 수있는 방법이 있습니까? 현재 Fragments에 대한 적절한 참조를 사용할 수 있습니까? 다른 해결책이있을 수 있습니까? 고맙습니다.

답변

4

그런 다음 FragmentPagerAdapter가 getItem()을 호출 할 때 디버깅 중이며 오리엔테이션 변경 이벤트가 발생하면 메소드가 호출되지 않습니다. ViewPager는 오래된 조각에 대한 참조를 보유합니다.

조각이 구성 변경에있는 것처럼 조각을 자동으로 다시 만들어야합니다. 예외는 setRetainInstance(true)을 사용한 경우이며,이 경우 이전과 동일한 프래그먼트 객체 여야합니다.

그래서 ViewPager에서 getItem()을 다시 호출하도록 강제 할 수있는 방법이 있습니까? 그렇다면 현재 Fragments에 대한 적절한 참조를 사용할 수 있습니까?

거기에있는 조각에는 어떤 문제가 있습니까?

+0

거기에'setRetainInstance()'를 사용하지 않습니다. 문제는 '오리엔테이션 변경'후에 나타나는 팝업 예외입니다. 난 단지'onActivityCreated()'가 양쪽 모두에 대해 실행되는 조건을 검사했기 때문에 이전의 Fragments가 사용되고 있다고 가정합니다. – Eugene

+0

@siik :이 refresh() 메소드는 언제 호출합니까? 그리고 언제 새롭게 생성 된 파편을 꺼내서 (해) '해시 테이블'을 채우고 있습니까? – CommonsWare

+0

'onPageScrollStateChanged()'('ViewPager.OnPageChangeListener' 인터페이스의 구현입니다. 즉,'Fragments' 사이에서 스 와이프 할 때)에서이'refresh()'메소드를 호출하고 있습니다. 그리고'FragmentPagerAdapter'를 확장 한 클래스의 getItem() 메소드에서'HashTable'을 채 웁니다. – Eugene

0

나는이 문제에 대한 솔루션을 찾고 어떤 일에 썼다, 많은 점을 파악했다 :

  • 사용 FragmentPagerAdapter 대신

  • FragmentStatePagerAdapter의 사용 FragmentStatePagerAdapter 대신 FragmentPagerAdapter

  • return POSITION_NONEgetItemPosition FragmentPagerAdapter 오버라이드

  • 당신이 조각

  • 많은 많은 많은 다른 사람의 역동적 인 변화를 필요로하는 경우 생성의 Eugene처럼, 나 자신에게 인스턴스를 관리 내 응용 프로그램에서

, ... FragmentPagerAdapter를 사용하지 않는 조각. 나는 하나의 특별한 클래스 안에서 HashMap<String,Fragment>을 유지하므로, 조각들은 결코 릴리스되지 않고, 내 애플 리케이션을 빠르게 할 수있다. (그러나 더 많은 자원을 소비한다.)

태블릿 (및 전화)을 회전 할 때 문제가 발생했습니다. getItem(int)은 더 이상 호출되지 않아 변경할 수 없습니다. 정말 해결책을 찾아 낼 때까지

는 정말 많은 시간을 보낸, 그래서 ...

나에게 많은 여러 번하는 데 도움이 StackOverflow의 커뮤니티와 공유 할이 문제에 대한 솔루션을 필요로 열심히 일하지만 그것을 찾기 위해, 매우 간단합니다 :

그냥 FragmentPagerAdapter의 생성자에서 FragmentManager에 대한 참조를 유지하는 것은 확장 :

public class Manager_Pager extends FragmentPagerAdapter { 

    private final FragmentManager mFragmentManager; 
    private final FragmentActivity mContext; 

    public Manager_Pager(FragmentActivity context) { 

     super(context.getSupportFragmentManager()); 

     this.mContext = context; 
     this.mFragmentManager = context.getSupportFragmentManager(); 
    } 

    @Override 
    public int getItemPosition(Object object) { 

// here, check if this fragment is an instance of the 
// ***FragmentClass_of_you_want_be_dynamic*** 

     if (object instanceof FragmentClass_of_you_want_be_dynamic) { 

// if true, remove from ***FragmentManager*** and return ***POSITION_NONE*** 
// to force a call to ***getItem*** 

      mFragmentManager.beginTransaction().remove((Fragment) object).commit(); 
      return POSITION_NONE; 
     } 

     //don't return POSITION_NONE, avoid fragment recreation. 
     return super.getItemPosition(object); 
    } 

    @Override 
    public Fragment getItem(int position) { 


     if (position == MY_DYNAMIC_FRAGMENT_INDEX){ 

      Bundle args = new Bundle(); 
      args.putString("anything", position); 
      args.putString("created_at", ALITEC.Utils.timeToStr()); 

      return Fragment.instantiate(mContext, FragmentClass_of_you_want_be_dynamic.class.getName(), args); 

     }else 

     if (position == OTHER){ 

      //... 

     }else 

     return Fragment.instantiate(mContext, FragmentDefault.class.getName(), null); 

    } 
} 

그게 전부. 그리고 그것은 매력처럼 작동합니다 ...

+1

해당 항목이 작동하지 않음 getItem은 방향 변경을 요청하지 않습니다. – JosephM

+0

this.mFragmentManager = context.getSupportFragmentManager(); – alijunior

관련 문제