【问题标题】:Fragment inside ViewPager returning null in getView()ViewPager 中的片段在 getView() 中返回 null
【发布时间】:2013-10-07 02:33:49
【问题描述】:

在我的应用程序中,我有一个 ViewPager,在该 ViewPager 中大约有 17 个片段。我已经为纵向和横向设计了布局。 当我旋转屏幕时,getView() 方法返回一个空对象,不知道为什么会这样,我使用了setRetainInstance(true),但还是一样,我使用PagerStateFragmentAdapter 作为我的适配器实施。

为什么会发生这种情况?

提前谢谢你。

编辑

MainActivity

public class MainActivity extends FragmentActivity implements ViewPagerController{
    public static final String READ_TYPE = "Read_type";
    private static final String TAG = MainActivity.class.getSimpleName();
    private int mReadType;
    private ViewPager mBookPager;

    @Override
    public void goToNextPage() {
        // TODO Auto-generated method stub
        int currentPage = mBookPager.getCurrentItem();
        if(currentPage+1 < mBookPager.getAdapter().getCount()){
            FragmentPagerAdapter adapter = (FragmentPagerAdapter)mBookPager.getAdapter();
            BookPageFragment bookPage = (BookPageFragment)adapter.getItem(currentPage);
            bookPage.setCurrentPage(false);

            bookPage = (BookPageFragment)adapter.getItem(currentPage+1);
            bookPage.setCurrentPage(true);
            mBookPager.setCurrentItem(currentPage+1, true);
        }
    }

    @Override
    public void goToPreviousPage() {
        // TODO Auto-generated method stub
        int currentPage = mBookPager.getCurrentItem();
        if(currentPage >= 0){
            mBookPager.setCurrentItem(currentPage-1,true);
        }
    }

    @Override
    public void onBackPressed() {
        // TODO Auto-generated method stub
        finish();
        overridePendingTransition(R.anim.anim_move_to_right,R.anim.anim_from_left_to_right);
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        Log.i(TAG,"onDestroy");
        mBookPager.removeAllViews();
        mBookPager = null;
        super.onDestroy();
    }

    @Override
    protected void onCreate(Bundle arg0) {
        // TODO Auto-generated method stub
        super.onCreate(arg0);
        setContentView(R.layout.main_layout);
        overridePendingTransition(R.anim.anim_from_right_to_left, R.anim.anim_move_to_left);
        initReadType();
        mBookPager = (ViewPager)findViewById(R.id.mainLayout_mainViewPager);
        initViewPager();

    }

    private void initReadType(){
        mReadType = getIntent().getIntExtra(READ_TYPE, -1);
    }

    private void initViewPager(){
        BookPagerAdapter mPagerAdapter = new BookPagerAdapter(getSupportFragmentManager(),mReadType);
        ((BookPageFragment)mPagerAdapter.getItem(0)).setCurrentPage(true);
        mBookPager.setAdapter(mPagerAdapter);
        mBookPager.setOnPageChangeListener(mOnPageChangeListener);
    }

    private OnPageChangeListener mOnPageChangeListener = new OnPageChangeListener(){

        @Override
        public void onPageScrollStateChanged(int arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onPageSelected(int selection) {
            // TODO Auto-generated method stub
            BookPagerAdapter bookAdapter = (BookPagerAdapter)mBookPager.getAdapter();
            BookPageFragment fragment = (BookPageFragment)bookAdapter.getItem(selection);
            if(selection > 0){
                bookAdapter.getItem(selection - 1).onPause();
//              bookAdapter.getItem(selection - 1).onDestroy();
            }
            if(selection + 1 < bookAdapter.getCount() && (bookAdapter.getItem(selection + 1) != null)){
                bookAdapter.getItem(selection + 1).onPause();
            }
            fragment.setCurrentPage(true);
            fragment.onResume();
        }

    };

    public static class BookPagerAdapter extends FragmentStatePagerAdapter{
        private List<Fragment> mBookPagesList;
        private int mReadType;

        public BookPagerAdapter(FragmentManager fm,int readType) {
            super(fm);
            // TODO Auto-generated constructor stub
            mReadType = readType;
            initPages();
        }

        @Override
        public Fragment getItem(int position) {
            // TODO Auto-generated method stub
            return mBookPagesList.get(position);
        }

        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            return mBookPagesList.size();
        }

        private void initPages(){
            mBookPagesList = new ArrayList<Fragment>();
            mBookPagesList.add(FirstPageFragment.newInstance(mReadType));
            mBookPagesList.add(SecondPageFragment.newInstance(mReadType));
            mBookPagesList.add(ThirdPageFragment.newInstance(mReadType));
            mBookPagesList.add(FourthPageFragment.newInstance(mReadType));
            mBookPagesList.add(FifthPageFragment.newInstance(mReadType));
            mBookPagesList.add(SixthPageFragment.newInstance(mReadType));
            mBookPagesList.add(SeventhPageFragment.newInstance(mReadType));
            mBookPagesList.add(EigthPageFragment.newInstance(mReadType));
            mBookPagesList.add(NinethPageFragment.newInstance(mReadType));
            mBookPagesList.add(TenthPageFragment.newInstance(mReadType));
            mBookPagesList.add(EleventhPageFragment.newInstance(mReadType));
            mBookPagesList.add(TwelvethPageFragment.newInstance(mReadType));
            mBookPagesList.add(ThirteenthPageFragment.newInstance(mReadType));
            mBookPagesList.add(FourteenthPageFragment.newInstance(mReadType));
            mBookPagesList.add(FifteenthPageFragment.newInstance(mReadType));
            mBookPagesList.add(SixteenthPageFragment.newInstance(mReadType));
            mBookPagesList.add(SeventeenthPageFragment.newInstance(mReadType));
            mBookPagesList.add(CreditsPageFragment.newInstance(mReadType));
        }
    }
}

BookPageFragment

public abstract class BookPageFragment extends Fragment{
public static final String TAG = BookPageFragment.class.getSimpleName();

public static final int AUTO_PLAY = 1;
public static final int READ_WITH_ME = 2;
public static final int READ_TO_MYSELF = 3;

private ViewPagerController mPageController;
protected final static String READ_TYPE_KEY = "readType";

private boolean mIsCurrentPage;

private int mCurrentWordIndex;
private MediaPlayer mMediaPlayer;
private BookPage mBookPage;
private SpeechController mSpeechController;

private TextHighlightController mCurrentHighlightController;
protected List<TextHighlightController> mHighlighters;
private int mCurrentHighlightIndex;

public abstract int getJsonId();
public abstract int getAudioResourceId();
protected abstract int[] getParagraphsTextView();
protected abstract int[] getParagraphsStringRes();
protected abstract int[] getPopupButtonsId();

public BookPageFragment(){
    mIsCurrentPage = false;
    mCurrentHighlightIndex = 0;
}

public void endAudioPlayback(){
    if(getReadTypeFromArgs() == AUTO_PLAY){
        mPageController.goToNextPage();
    }
}

private void loadHighlighters(){
    int[] paragraphsTextViews = getParagraphsTextView();
    int[] stringRes = getParagraphsStringRes();
    for(int i=0;i<paragraphsTextViews.length;i++){
        int currentParagraph = paragraphsTextViews[i];
        int stringId = stringRes[i];
        TextView paragraph = (TextView)getView().findViewById(currentParagraph);
        TextHighlightController controller = TextHighlightController.newInstance(getActivity(), paragraph, stringId);
        addHighlighter(controller);
    }
}

public final void highlightNextWord(){
    if(!mCurrentHighlightController.highlightNextWord()){
        mCurrentHighlightIndex++;
        if(mCurrentHighlightIndex < mHighlighters.size()){
            mCurrentHighlightController = mHighlighters.get(mCurrentHighlightIndex);
            mCurrentHighlightController.highlightNextWord();
        }
    }
}

@Override
public void onAttach(Activity activity) {
    // TODO Auto-generated method stub
    super.onAttach(activity);
    Log.i(TAG,"onAttach");
    try{
        mPageController = (ViewPagerController)activity;
    }catch(ClassCastException e){
        throw new IllegalArgumentException("Activity not implementing ViewPagerController");
    }
}

@Override
public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    Log.i(TAG,"onCreate");
}

@Override
public void onDetach() {
    // TODO Auto-generated method stub
    super.onDetach();
    resetAll();
    Log.i(TAG,"onDetach");
}

public void goToNextPage(){
    mPageController.goToNextPage();
}

public void goToPreviousPage(){
    mPageController.goToPreviousPage();
}

public void setCurrentPage(boolean isCurrentPage){
    mIsCurrentPage = isCurrentPage;
}

public boolean isCurrentPage(){
    return mIsCurrentPage;
}

@Override
public void onStart() {
    // TODO Auto-generated method stub
    super.onStart();
    Log.i(TAG,"onStart");
}

@Override
public void onResume() {
    // TODO Auto-generated method stub
    Log.i(TAG,"onResume");
    super.onResume();
    resetAll();
    configureBookPage();
}

public final void startWithAutoPlay(){
    disablePopupButtons();
    initAudioPlayback();
}

public final void startWithRead(){
    initAudioPlayback();
}

private long prevWordStartTime = 0;
public final long getNextWordStart(){
    long wordStart=-1;
    if(mCurrentWordIndex < mBookPage.getWordList().size()){
        Word currentWord = mBookPage.getWordList().get(mCurrentWordIndex);
        wordStart = currentWord.getStartTime() - prevWordStartTime;
        wordStart = wordStart + currentWord.getWordLength() - 25;
        prevWordStartTime = currentWord.getEndTime();
        mCurrentWordIndex++;
    }
    return wordStart;
}

public final long getNextWordLength(){
    long wordLength;
    if(mCurrentWordIndex < mBookPage.getWordList().size()){
        Word currentWord = mBookPage.getWordList().get(mCurrentWordIndex);
        if(mCurrentWordIndex == 0){
            wordLength= currentWord.getStartTime();
        }else{
            wordLength = currentWord.getWordLength();
        }
        mCurrentWordIndex++;
    }else{
        wordLength = -1;
    }
    return wordLength;
}

public final void startPlayback(){
    mMediaPlayer = MediaPlayer.create(getActivity(), getAudioResourceId());
    mMediaPlayer.start();
}

@Override
public void onPause() {
    // TODO Auto-generated method stub
    Log.i(TAG,"onPause");
    mIsCurrentPage = false;
    if(mSpeechController != null){
        mSpeechController.stopHighlighting();
    }
    if(mMediaPlayer != null){
        try{
            mMediaPlayer.stop();
            mMediaPlayer.release();
        }catch(Exception e){

        }
    }
    resetHighlighters();
    resetAll();
    super.onPause();
}

@Override
public void onStop() {
    // TODO Auto-generated method stub
    super.onStop();
    Log.i(TAG,"onStop");
}

protected void addHighlighter(TextHighlightController controller){
    if(mHighlighters == null){
        mHighlighters = new ArrayList<TextHighlightController>();
    }
    mHighlighters.add(controller);
}

private void resetHighlighters(){
    if(mHighlighters != null){
        for(TextHighlightController controller : mHighlighters){
            controller.reset();
        }
    }
    mCurrentHighlightIndex = 0;
    mCurrentWordIndex = 0;
}

private void resetAll(){
    mCurrentWordIndex = 0;
    mCurrentHighlightIndex = 0;
    if(mMediaPlayer != null){
        try{
            mMediaPlayer.reset();
        }catch(Exception e){

        }
    }
    if(mCurrentHighlightController != null){
        mCurrentHighlightController.reset();
    }
    if(mSpeechController != null){
        Message msg = mSpeechController.obtainMessage(SpeechController.END_AUDIO);
        mSpeechController.sendMessage(msg);
    }
    if(mHighlighters != null){
        for(TextHighlightController controller : mHighlighters){
            controller.reset();
        }
    }
}

private void initAudioPlayback(){
    if(getJsonId() != 0){
        initHighlightersList();
        loadJson();
        mSpeechController = new SpeechController(this);
        Message msg = mSpeechController.obtainMessage(SpeechController.START_AUTO_PLAY);
        mSpeechController.sendMessageDelayed(msg, 1000);
    }
}

private void disablePopupButtons(){
    if(getView() != null){
        int[] buttonsId = getPopupButtonsId();
        for(int currentButtonId : buttonsId){
            getView().findViewById(currentButtonId).setVisibility(View.INVISIBLE);
        }
    }
}

private void initHighlightersList(){
    loadHighlighters();
    if(mHighlighters != null)
        mCurrentHighlightController = mHighlighters.get(mCurrentHighlightIndex);
}

private void loadJson(){
    Gson gson = new Gson();
    InputStream jsonStream = getResources().openRawResource(getJsonId());
    InputStreamReader jsonReader = new InputStreamReader(jsonStream);
    mBookPage = gson.fromJson(jsonReader, BookPage.class);
}

private void configureBookPage(){
    int currentReadType = getReadTypeFromArgs();
    Log.i(TAG,"GotReadType");
    switch(currentReadType){
    case AUTO_PLAY:
        if(mIsCurrentPage){
            startWithAutoPlay();
        }
        break;
    case READ_WITH_ME:
        if(mIsCurrentPage){
            startWithRead();
        }
        break;
    case READ_TO_MYSELF:
        //Should do Nothing
        break;
    default:
        throw new IllegalArgumentException("You must select one of the reading types of BookPageFragment");
    }
}

protected int getReadTypeFromArgs(){
    return getArguments().getInt(READ_TYPE_KEY);
}

}

LOGCAT

    09-30 22:56:37.602: E/AndroidRuntime(7640): FATAL EXCEPTION: main
09-30 22:56:37.602: E/AndroidRuntime(7640): java.lang.NullPointerException
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.mobimanage.kagadventures.fragment.BookPageFragment.loadHighlighters(BookPageFragment.java:68)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.mobimanage.kagadventures.fragment.BookPageFragment.initHighlightersList(BookPageFragment.java:275)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.mobimanage.kagadventures.fragment.BookPageFragment.initAudioPlayback(BookPageFragment.java:257)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.mobimanage.kagadventures.fragment.BookPageFragment.startWithRead(BookPageFragment.java:149)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.mobimanage.kagadventures.fragment.BookPageFragment.configureBookPage(BookPageFragment.java:298)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.mobimanage.kagadventures.fragment.BookPageFragment.onResume(BookPageFragment.java:140)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.mobimanage.kagadventures.MainActivity$1.onPageSelected(MainActivity.java:136)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.support.v4.view.ViewPager.scrollToItem(ViewPager.java:567)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:551)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.support.v4.view.ViewPager.onTouchEvent(ViewPager.java:2008)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.View.dispatchTouchEvent(View.java:7253)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2168)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1903)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2215)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1458)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.app.Activity.dispatchTouchEvent(Activity.java:2410)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2163)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.View.dispatchPointerEvent(View.java:7433)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3220)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3165)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4292)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4271)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4363)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:179)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.os.MessageQueue.nativePollOnce(Native Method)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.os.MessageQueue.next(MessageQueue.java:125)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.os.Looper.loop(Looper.java:124)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at android.app.ActivityThread.main(ActivityThread.java:5227)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at java.lang.reflect.Method.invokeNative(Native Method)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at java.lang.reflect.Method.invoke(Method.java:511)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
09-30 22:56:37.602: E/AndroidRuntime(7640):     at dalvik.system.NativeStart.main(Native Method)

【问题讨论】:

  • 你能发布相应的代码吗?
  • 完成!有代码
  • 没关系。需要播种您的 PagerStateFragmentAdapter。
  • 为了帮助我们需要查看代码以供我们分析,而不仅仅是您认为相关的代码。我们也需要查看 logcat。
  • 有logcat,它说错误在'loadHighlighters'中,当我调试时我看到getView()它返回null

标签: android fragment


【解决方案1】:

而不是使用getItem来获取当前页面使用

(BookPageFragment) mBookPagerAdapter.instantiateItem(mBookPager, mBookPager.getCurrentItem());

这会返回一个对实际有视图的现有片段的引用。

【讨论】:

  • 小建议:第一个mBookPager是适配器,第二个是viewPager
  • 这个问题是双重的,但是:首先,它依赖于重写的 instantiateItem(),根据实现,它可能不仅仅是返回前一个片段,而是创建一个新片段。其次,不推荐将 View 作为第一个参数的调用。 -- 我找到了一个可行的解决方案,我会把它作为答案发布。
  • 你救了我的命 :-)
【解决方案2】:

如果您像往常一样在页面适配器中跟踪片段,请向其中添加以下函数:

private SparseArray<PageType> fragments;
...
public PageType getFragment(int position) {
  return fragments.get(position);
}

然后您可以使用它来查询片段。 getView() 已经可以正常工作了:

PageType page = (PageType) pagesAdapter.getFragment(pager.getCurrentItem());
View view = page.getView().findViewById(R.id.whatever);
view.invalidate();

【讨论】:

  • 这真的有效吗? Androd 可能决定销毁一个片段,它仍然在您的片段数组中,然后重新创建它,然后您的数组中有一个过时的版本。不过,我还不确定这是否会发生。
【解决方案3】:

对于android.support.v4.app.FragmentManager,setRetainInstance 会被忽略。

对我有用的解决方案是在调用 super.OnCreate 之前删除我活动的 onCreate 中保存的片段。

if(savedInstanceState != null) {
    savedInstanceState.remove("android:support:fragments");
}

这对我有用,就像我期望 setRetainInstance(true); 在片段本身中工作一样。

我找到了这个解决方案here

*请注意,如果您从任何片段调用 DialogFragment,如果您使用此解决方案,它们将在方向更改时关闭。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-30
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    • 2016-05-19
    • 2014-12-27
    相关资源
    最近更新 更多