ViewPager中的片段返回空对象onResume

时间:2015-07-30 20:09:34

标签: android android-fragments android-viewpager oncreate fragmentpageradapter

我使用FragmentPagerAdapter从片段切换。我需要在制作片段开关时调用一些函数,并且在OnPause和OnResume上遇到一些麻烦,所以THIS问题我已经实现了一个接口OnPageSelectListener:

public interface OnPageSelectListener {
    void onPageSelected();
    void onPageNotVisible();
}

只要此页面到达前台,它就会调用OnPageSelected函数。工作得很好,除了我想在我的适配器上调用一个函数。我认为这样可行,除了我的适配器一直返回NULL(即使它被初始化并且数据在我的列表视图中被加载为首选)。

    public class AfterCheckFragment extends Fragment implements OnPageSelectListener{


        private   ListView listView;
        private List<Check> checkList;
        private CheckListAdapter adapter;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view =  inflater.inflate(R.layout.fragment_check, container, false);

        System.out.println("VIEW create  called");

//(.. some other stuff, not relevant for question..)

        //initializing the adapter
          listView = (ListView) view.findViewById(R.id.listView);
        adapter = new CheckListAdapter(checkList,getActivity(),trainPosition);

        listView.setAdapter(adapter);
        adapter.handleButtonVisibility();
        return view;

    }
@Override
    public void onPageSelected() {
        if(this.adapter != null) {
            System.out.println("adapter not null");
            this.adapter.checkForActive();
        }else{
            System.out.println("Adapter is NULL");
        }

    }

        @Override
        public void onPageNotVisible() { //page is moved to backgroung
            System.out.println("AFTER not active any more ");
        }
    }

现在是我的问题:为什么适配器(或片段中的任何其他对象)在返回我的片段时会返回null?当fragmentPager初始化时,片段的onActivityCreate函数被调用一次,但之后不再调用,并且适配器返回null ....

6 个答案:

答案 0 :(得分:3)

你必须在初始化适配器和setAdapter()之后调用onPageSelected()否则适配器将始终返回null

答案 1 :(得分:2)

当用户更改页面时,

ViewPager将创建和销毁片段(请参阅ViewPager.setOffscreenPageLimit())。所以onActivityCreated()仅在片段第一次被恢复或设置时被调用。因此,可以创建片段而无需调用onActivityCreated()

我会建议覆盖onActivityCreated()并在那里设置适配器,而不是onViewCreated()。没有创建视图就不能显示片段,所以这是一个做这种事情的好地方。

如果您的OnPageSelectListener逻辑有效,那就太好了。我发现知道片段实际位于用户面前的最佳方式是覆盖setPrimaryItem()中的FragmentPagerAdapter。将页面移出视图事件有点棘手,因为您必须保留对先前setPrimaryItem()调用中的片段的引用。

答案 2 :(得分:2)

以下为什么我认为您的@echo off setlocal & pushd . call :FindNeedle "%~1" bar :: My real script shuttles a few variables out of the local scope popd & endlocal & goto :EOF :: Subroutine :FindNeedle setlocal ENABLEEXTENSIONS :: Category set REQ=%~1 :: Subcategory set NEEDLE=%~2 :: This call will either end up setting the HAYSTACK variable :: (see below) or not doing anything at all. It also suppresses :: error output if the call "fails" call :CHECK_%REQ% > NUL 2>&1 :: Jump over the "subroutines" used to set HAYSTACK goto :END_CHECK :CHECK_FOO set HAYSTACK=foo goto :EOF :CHECK_BAR set HAYSTACK=foo bar goto :EOF :CHECK_BAZ set HAYSTACK=foo bar baz goto :EOF :END_CHECK :: FOUND should hold the name of the NEEDLE if found or be empty set FOUND= :: This checks that we have a HAYSTACK to look in. It then shows :: what the HAYSTACK looks like and iterates over its elements. :: Echoing each element it then checks if an element matches the :: NEEDLE we're looking for and calls :SetVar to avoid delayed :: expansion woes and set FOUND if not "%HAYSTACK%" == "" @( echo HAYSTACK ^= %HAYSTACK% for %%i in (%HAYSTACK%) do @( echo %%i if "%NEEDLE%" == "%%i" echo Matched %%i&call :SetVar FOUND %%i ) ) else @( echo ERROR: Empty haystack endlocal & goto :EOF ) if "%FOUND%" == "" @( echo ERROR: %NEEDLE% is not supported by %REQ%&endlocal&goto :EOF ) echo Found: %FOUND% :: This subroutine also normally would shuttle out variables endlocal & goto :EOF :: This subroutine is a trick to set a variable inside of a :: for loop without using delayed expansion :SetVar set %~1=%~2&goto :EOF (我称之为CheckListAdapter)为空:

  1. 您将listAdapter提供给pagerAdapter
  2. ViewPager要求ViewPager提供新的pagerAdapter
  3. Fragment告诉ViewPager使用它
  4. FragmentManager被称为
  5. 您尝试使用onPageSelected。目前还没有初始化。 (NPE)
  6. listAdapter将片段拖入其所有阶段。
  7. FragmentManager被召唤。您的onCreateView已创建。
  8. 不要尝试使用其外部片段的内部数据。它意味着作为一个独立的单元工作,如果你以不同的方式使用它,它将不会很好。由于片段是在稍后阶段初始化的,因此您无法像预期的那样使用它 您可以尝试在片段中执行您想要执行的操作,而不是listAdapter,或者在托管pagerAdapter中编写方法,并在准备好时从片段中调用它,甚至可以启动事件。

答案 3 :(得分:1)

这是因为Viewpager在调用oncreateView()/ onActivityCreated()中的片段之前调用OnpageSelected方式。

最好的方法是在Fragment的构造函数中膨胀您的视图并设置适配器。

使用成员变量存储片段是否处于活动状态。并使用oncreateview()中的变量来调用适配器上的函数。

答案 4 :(得分:1)

为什么不在你的寻呼机中使用viewpager.addOnPageChangeListener后,在你的片段上设置了适配器和setOffscreenPageLimit()而不是implements

下面是示例代码:

viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
       if(position == 1){  // if you want the second page, for example
           //Your code here
       }
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
});

当您在设置Activity的{​​{1}}内进行操作。

答案 5 :(得分:0)

对我来说,我不得不在我的viewpager上打电话:

myViewPager.setSaveFromParentEnabled(false);