简体   繁体   English

在onresume之后,ViewPager中的片段为null

[英]Fragments in ViewPager are null after onresume

I'm writing an application that has 2 Tabs in its MainActivity . 我正在编写一个在MainActivity中有2个Tabs的应用程序。 I created the Activity Template with the Android Plugin for Eclipse and adapted it. 我使用适用于Eclipse的Android插件创建了活动模板并对其进行了调整。 Anyway when I resume the Application after a while the Fragments will be null. 无论如何,当我在一段时间后恢复应用程序时,片段将为空。

Here is the code of my Activity (I removed "unimportant" parts) 这是我的活动的代码(我删除了“不重要的”部分)

public class MainActivity extends FragmentActivity implements
    ActionBar.TabListener {

/**
 * The {@link android.support.v4.view.PagerAdapter} that will provide
 * fragments for each of the sections. We use a
 * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
 * will keep every loaded fragment in memory. If this becomes too memory
 * intensive, it may be best to switch to a
 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
 */
SectionsPagerAdapter mSectionsPagerAdapter;

private static final String ARG_SECTION_NUMBER = "section_number";

/**
 * Fragment to display markets on a {@link GoogleMap}.
 */
private GluehweinMapFragment mGluehweinMapFragment;

/**
 * Fragment to display available markets as list.
 */
private GluehweinListFragment mGluehweinListFragment;


/**
 * The {@link ViewPager} that will host the section contents.
 */
ViewPager mViewPager;



/*
 * (non-Javadoc)
 * 
 * @see android.support.v4.app.FragmentActivity#onCreate(android.os.Bundle)
 */
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);


    setContentView(R.layout.activity_main);


    initSectionsPagerAdapter();
//[...]

}

private void initSectionsPagerAdapter() {
    if (mSectionsPagerAdapter == null || mViewPager == null) {
        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        // Create the adapter that will return a fragment for each of the
        // three
        // primary sections of the app.
        mSectionsPagerAdapter = new SectionsPagerAdapter(
                getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        // When swiping between different sections, select the corresponding
        // tab. We can also use ActionBar.Tab#select() to do this if we have
        // a reference to the Tab.
        mViewPager
                .setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                    @Override
                    public void onPageSelected(int position) {
                        switch (position) {
                        case 0:
                            break;

                        }
                        refreshFragments();
                        actionBar.setSelectedNavigationItem(position);
                    }
                });
        actionBar.getSelectedNavigationIndex();

        // For each of the sections in the app, add a tab to the action bar.
        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            // Create a tab with text corresponding to the page title
            // defined by
            // the adapter. Also specify this Activity object, which
            // implements
            // the TabListener interface, as the callback (listener) for
            // when
            // this tab is selected.
            actionBar.addTab(actionBar.newTab()
                    .setText(mSectionsPagerAdapter.getPageTitle(i))
                    .setTabListener(this));
        }
    }
}



/**
 * Hides or shows the closed markets on the list and map
 */
private void updateVisibility() {
    if (this.mGluehweinMapFragment != null) {
        mGluehweinMapFragment.updateVisibility();
    }
    if (this.mGluehweinListFragment != null) {
        mGluehweinListFragment.updateVisibility();
    }
}

@Override
public void onTabSelected(ActionBar.Tab tab,
        FragmentTransaction fragmentTransaction) {

    mViewPager.setCurrentItem(tab.getPosition());
    invalidateOptionsMenu();
}

@Override
public void onTabUnselected(ActionBar.Tab tab,
        FragmentTransaction fragmentTransaction) {
}

@Override
public void onTabReselected(ActionBar.Tab tab,
        FragmentTransaction fragmentTransaction) {
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
 * one of the sections/tabs/pages.
 */
public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a DummySectionFragment (defined as a static inner class
        // below) with the page number as its lone argument.
        Fragment fragment = null;

        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, position + 1);

        switch (position) {
        case 0:
            // position 0 is the Map
            if (mGluehweinMapFragment == null) {
                mGluehweinMapFragment = new GluehweinMapFragment();
            }
            fragment = mGluehweinMapFragment;
            break;
        case 1:
            // position 1 is the List
            if (mGluehweinListFragment == null) {
                mGluehweinListFragment = new GluehweinListFragment();
            }
            fragment = mGluehweinListFragment;
            break;
        }
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        Locale l = Locale.getDefault();
        switch (position) {
        case 0:
            return getString(R.string.tab_map).toUpperCase(l);
        case 1:
            return getString(R.string.tab_list).toUpperCase(l);
        }
        return null;
    }

}

@Override
protected void onResume() {
    // on resume, restart requesting location updates
    super.onResume();
    //[..]
    initSectionsPagerAdapter();
    //some calls on the fragments which are null here!!!
    refreshFragments();
}



/**
 * Notifies the Fragments in the Tabs that data has changed
 */
private void refreshFragments() {
    if (this.mGluehweinMapFragment != null) {
        mGluehweinMapFragment.updateVisibility();
    }
    if (this.mGluehweinListFragment != null) {
        mGluehweinListFragment.updateVisibility();
    }
}   

 }

I asked a colleague and he said me that its not good to keep the two Fragments as members in my Activity , because Android eventually would create a new instance of the Fragments onResume and this is why my references are null. 我问了一位同事,他告诉我,将两个片段保留为我的Activity成员并不好,因为Android最终会创建一个新的Fragments onResume实例,这就是我的引用为空的原因。 But he could not tell me how to fix my problem. 但他无法告诉我如何解决我的问题。 I was thinking about writing a getFragment() method that would use a FragmentManager to get the fragments, but I don't know how to get my fragments in a state, where I can read them with a FragmentManager . 我正在考虑编写一个getFragment()方法,该方法将使用FragmentManager来获取片段,但我不知道如何将片段置于一个状态,我可以用FragmentManager读取它们。

Thank you in advance! 先感谢您!

Your colleague is right: it's not a good practice to use references to fragments in your activity's variables. 你的同事是对的:在你的活动变量中使用对片段的引用并不是一个好习惯。 Your activity will be destroyed, eg when you rotate the screen, and the references may lead to memory leaks. 您的活动将被销毁,例如当您旋转屏幕时,参考可能会导致内存泄漏。

As for your problem, move the code that initialises the ViewPager (your initSectionsPagerAdapter() method) to onResume . 至于你的问题,将初始化ViewPager (你的initSectionsPagerAdapter()方法)的代码移动到onResume It will be called when the activity is first started as well as when it becomes visible, eg when another app that was on top is closed. 它将在活动首次启动时以及何时变为可见时被调用,例如,当顶部的另一个应用程序关闭时。 You don't need your current code in onResume . 您不需要onResume的当前代码。

EDIT: 编辑:

When you create a fragment, don't store the reference to it in activity's variables. 创建片段时,请勿在活动的变量中存储对它的引用。 To access the fragments later, you can use: 要稍后访问片段,您可以使用:

FragmentManager fm = this.getFragmentManager();
GluehweinMapFragment f1 = (GluehweinMapFragment)fm.getFragments().get(0); // to get one fragment

for (Fragment f : fm.getFragments()) { // to loop through fragments and checking their type
    if (f instanceof GluehweinMapFragment) {
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM