2017-02-16 70 views
0

只是片段的許多問題之一。 在Activity.onCreate()方法中,我正在初始化一個ViewPager,其中有兩個FragmentsViewPager的第二個片段尚未實例化

viewPager = (ViewPager) findViewById(R.id.viewpager); 
    viewPager.setOffscreenPageLimit(1); 
    adapter = new ViewPagerAdapter(getSupportFragmentManager()); 
    adapter.addFragment(new AutoFragment(), getString(R.string.song_header_automatic)); 
    adapter.addFragment(new ManualFragment(), getString(R.string.song_header_manual)); 
    adapter.notifyDataSetChanged(); 
    viewPager.setAdapter(adapter); 

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); 
    tabLayout.setupWithViewPager(viewPager); 

之後,我需要在ViewPager的第二個片段中的View上執行一個操作。

((Fragment) adapter.getItem(1)).getView().findViewById(...) 

但它提供了NPE,因爲用戶從不瀏覽到第二個片段,因此它尚未連接。以相同的方式訪問第一個片段的元素不會產生任何問題。

不應該setOffscreenPageLimit(1)方法告訴Android也渲染第二個片段?

我也試過在適配器裏面沒有調用destroyItem的超級方法,但沒有運氣,因爲問題是片段甚至沒有初始化。

public class ViewPagerAdapter extends FragmentStatePagerAdapter { 
    private final List<Fragment> mFragmentList = new ArrayList<>(); 
    private final List<String> mFragmentTitleList = new ArrayList<>(); 

    public ViewPagerAdapter(FragmentManager manager) { 
     super(manager); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     return mFragmentList.get(position); 
    } 

    @Override 
    public int getCount() { 
     return mFragmentList.size(); 
    } 

    public void addFragment(Fragment fragment, String title) { 
     mFragmentList.add(fragment); 
     mFragmentTitleList.add(title); 
    } 

    @Override 
    public CharSequence getPageTitle(int position) { 
     return mFragmentTitleList.get(position); 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) {} 
} 

我該如何強制它,以便不可見的片段被渲染?

注意:這個問題只發生在應用程序用戶,我無法重現它。我只有一次遇到這個問題,所以我認爲這是關於在正確的生命週期事件之後執行錯誤的操作。

+0

只是嘗試使用'FragmentPagerAdapter'而不是'FragmentStatePagerAdapter' –

+0

@EduardoHerzer任何想法,爲什麼這應該解決這個問題? – fillobotto

+0

查看答案...太久無法做評論 –

回答

0

由於FragmentStatePagerAdapter文件:當有頁面大量 ,變得更像一個列表視圖

這個版本的尋呼機的是比較有用的。當用戶看不到頁面時,他們的整個片段可能被破壞,只保留 該片段的保存狀態。這使得尋呼機能夠保持更少的與每個訪問頁面相關聯的存儲器而不是 FragmentPagerAdapter,代價是 在頁面之間切換時潛在的更多開銷。

您可以嘗試使用FragmentPagerAdapter代替。

編輯:

因爲它發生在少數設備,我想這是一個低內存設備。

您可能會嘗試重新加載第二個片段,並將args傳遞給它。

在您的適配器,實現替換片段的方法:當你要重新裝入一個新的數據第二個片段,只是做

public void replaceFragment(int index, Fragment fragment, String title) { 
    mFragmentList.set(index, fragment); 
    mFragmentTitleList.add(index, title); 
} 

Bundle fragmentArgs = new Bundle(); 
fragmentArgs.putSerializable("obj", obj); //data you want to pass 
fragmentArgs.putString("str", str); //data you want to pass 
ManualFragment manualFragment = new ManualFragment(); 
manualFragment.setArguments(fragmentArgs); 

adapter.replaceFragment(1, manualFragment, getString(R.string.song_header_manual)); 
adapter.notifyDataSetChanged(); 

然後在onCreateViewManualFragment,得到參數:

Object obj = (Object) getArguments().getSerializable("obj"); 
String str = getArguments().getString("str"); 

而且做w你必須做的恨。

編輯2:

由於OP想要另一種方法,這裏有雲......

做這樣的事情的答案:https://stackoverflow.com/a/24343211/2174489

這樣你就不會從另一個片段訪問視圖超出原來的範圍。我不喜歡像((Fragment) adapter.getItem(1)).getView().findViewById(...)這樣的想法。我寧願做((Fragment) adapter.getItem(1)).setTextViewText(...)

然後,在setTextViewText你可以測試你的視圖是否爲空。如果爲null,保存在字符串中的全局變量:

public void setTextViewText(String value){ 
    if (mTextView == null) 
     myGlobalValue = value; 
    else 
     mTextView.setText(value); 
} 

然後在onCreateView,你可以設置這個值:

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    ... 
    if (myGlobalValue != null) 
     mTextView.setText(myGlobalValue); 
    ... 
} 

讓我知道這是否解決了問題。

+0

有趣。我會更新測試版本,看看問題是否再次出現。 – fillobotto

+0

不幸的是問題依然存在。這聽起來更像是這個片段被插入,但它沒有附加到活動 – fillobotto

+0

@fillobotto我編輯了答案。也許你可以嘗試這種方法 –

相關問題