【问题标题】:Fragment in ViewPager returns empty object onResumeViewPager 中的 Fragment 返回空对象 onResume
【发布时间】:2026-01-23 15:30:01
【问题描述】:

我使用 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初始化时,会调用一次fragment的onActivityCreate函数,之后不再调用,并且适配器返回null....

【问题讨论】:

  • 接口需要Fragment(AfterCheckFragment)和继承的接口进行数据通信,我看不到。有时片段会调用接口中的公共/受保护方法,我没有看到。请至少发布 OnPageSelectListener 的代码,也可能为相关的 Adapter 发布代码。
  • 请发布适配器代码,因为您有代码 this.adapter.checkForActive() 并且您说“为什么适配器...返回 null...”?
  • 我刚刚注意到您发布的代码根本没有显示 FragmentPagerAdapter。我这样说是因为该类有自己的片段之间切换的方式,相关链接@developer.android.com/reference/android/support/v4/app/…。我认为引用 FragmentPagerAdapter 的代码也可能是相关的。

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    这就是为什么我认为您的CheckListAdapter(我会称之为listAdapter)为空:

    1. 您将pagerAdapter 提供给ViewPager
    2. ViewPagerpagerAdapter 请求新的Fragment
    3. ViewPager 告诉FragmentManager 使用它
    4. onPageSelected 被调用
    5. 您尝试使用listAdapter。此时还没有初始化。 (NPE)
    6. FragmentManager 将 Fragment 拖过所有阶段。
    7. onCreateView 被调用。您的 listAdapter 已创建。

    不要尝试使用片段外部的内部数据。它旨在作为一个独立的单元工作,如果您以不同的方式使用它,它不会很好。由于片段是在稍后阶段初始化的,因此您无法按预期使用它。
    您可以尝试在片段中而不是pagerAdapter 中做您想做的事情,或者在托管Activity 中编写一个方法,并在准备好时从片段中调用它,甚至启动一个事件。

    【讨论】:

      【解决方案3】:

      ViewPager 将在用户更改页面时创建和销毁片段(请参阅ViewPager.setOffscreenPageLimit())。所以onActivityCreated() 仅在第一次恢复或设置时才在片段上调用。因此,无需调用 onActivityCreated() 就可以创建片段。

      我建议您覆盖 onViewCreated() 并在那里设置您的适配器,而不是 onActivityCreated()。如果没有创建视图,任何片段都无法显示,所以这是做这类事情的好地方。

      如果您的 OnPageSelectListener 逻辑正常工作,那就太好了。我发现知道片段何时实际出现在用户面前的最佳方法是在FragmentPagerAdapter 中覆盖setPrimaryItem()。让页面脱离视图事件有点棘手,因为您必须保留对先前 setPrimaryItem() 调用中的片段的引用。

      【讨论】:

      • 嗨,克里斯,感谢您的回答。我按照您的建议在 onViewCreated 中实现了启动(尽管我在使用 onActivityCreated 时从来没有遇到过问题),而且仅在创建 viewpager 时才调用 onViewCreate。如果我返回视图,每次寻呼机返回 null 时......
      • 您能发布更多代码吗?我做了一个类似于你的测试应用程序,我没有任何问题。第 2 页的视图是在用户查看第 1 页时在屏幕外创建的,因此当用户滚动并调用 OnPageChangeListener.onPageSelected(2) 时,视图已经创建,所以...没问题。
      【解决方案4】:

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

      对您来说最好的方法是在 Fragment 的构造函数中扩充您的视图并设置适配器。

      或者

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

      【讨论】:

        【解决方案5】:

        你为什么不在你的寻呼机中使用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 中设置你的ViewPager

        【讨论】:

          【解决方案6】:

          对我来说,我必须在我的浏览器上调用它:

          myViewPager.setSaveFromParentEnabled(false);
          

          【讨论】: