I've been working with Android for a while, but fragments are a little new to me (as they are to most people probably). Anyway, I've got the below code, and it works fine. I've got three fragments, one in each tab. I'm wondering if it's normal for onCreateView to be called everytime I switch tabs, and does it make sense to do so? Shouldn't there be a way to NOT redraw the fragment every time the tab changes?
I'm converting this from an app that had 3 activities, one in each tab, and it seems like a waste to recreate the view every time the tab changes, when it used to be just fine having the views exist between tab changes...
BTW, this code borrowed from: http://thepseudocoder.wordpress.com/2011/10/04/android-tabs-the-fragment-way/
public class Tabs extends FragmentActivity implements
TabHost.OnTabChangeListener {
final String MAP_TAB = "Map";
final String IMAGES_TAB = "Images";
final String SETTINGS_TAB = "Settings";
TabHost mTabHost;
HashMap<String, TabInfo> mapTabInfo = new HashMap<String, TabInfo>();
TabInfo mLastTab = null;
private class TabInfo {
private String tag;
private Class clss;
private Bundle args;
private Fragment fragment;
TabInfo(String tag, Class clazz, Bundle args) {
this.tag = tag;
this.clss = clazz;
this.args = args;
}
}
class TabFactory implements TabContentFactory {
private final Context mContext;
public TabFactory(Context context) {
mContext = context;
}
public View createTabContent(String tag) {
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
initialiseTabHost(savedInstanceState);
if (savedInstanceState != null)
mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); //set the tab as per the saved state
}
protected void onSaveInstanceState(Bundle outState) {
outState.putString("tab", mTabHost.getCurrentTabTag()); //save the tab selected
super.onSaveInstanceState(outState);
}
private void initialiseTabHost(Bundle args) {
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
mTabHost.setup();
TabInfo tabInfo;
Tabs.addTab(this,
mTabHost,
mTabHost.newTabSpec(MAP_TAB).setIndicator(
MAP_TAB,
getResources().getDrawable(R.drawable.ic_tab_map_states)),
( tabInfo = new TabInfo(MAP_TAB, HMapFragment_NEW.class, args)));
mapTabInfo.put(tabInfo.tag, tabInfo);
Tabs.addTab(this,
mTabHost,
mTabHost.newTabSpec(IMAGES_TAB).setIndicator(
IMAGES_TAB,
getResources().getDrawable(R.drawable.ic_tab_gallery_states)),
( tabInfo = new TabInfo(IMAGES_TAB, ImageGridFragment.class, args)));
mapTabInfo.put(tabInfo.tag, tabInfo);
Tabs.addTab(this,
mTabHost,
mTabHost.newTabSpec(SETTINGS_TAB).setIndicator(
SETTINGS_TAB,
getResources().getDrawable(R.drawable.ic_tab_settings_states)),
( tabInfo = new TabInfo(SETTINGS_TAB, SettingsFragment.class, args)));
mapTabInfo.put(tabInfo.tag, tabInfo);
// Default to first tab
this.onTabChanged(MAP_TAB);
mTabHost.setOnTabChangedListener(this);
}
private static void addTab(Tabs activity, TabHost tabHost, TabHost.TabSpec tabSpec, TabInfo tabInfo) {
// Attach a Tab view factory to the spec
tabSpec.setContent(activity.new TabFactory(activity));
String tag = tabSpec.getTag();
// Check to see if we already have a fragment for this tab, probably
// from a previously saved state. If so, deactivate it, because our
// initial state is that a tab isn't shown.
tabInfo.fragment = activity.getSupportFragmentManager().findFragmentByTag(tag);
if (tabInfo.fragment != null && !tabInfo.fragment.isDetached()) {
FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction();
ft.detach(tabInfo.fragment);
ft.commit();
activity.getSupportFragmentManager().executePendingTransactions();
}
tabHost.addTab(tabSpec);
}
public void onTabChanged(String tag) {
TabInfo newTab = this.mapTabInfo.get(tag);
// if they've clicked to change tabs
if (mLastTab != newTab) {
FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction();
if (mLastTab != null)
if (mLastTab.fragment != null) ft.detach(mLastTab.fragment);
if (newTab != null) {
if (newTab.fragment == null) {
newTab.fragment = Fragment.instantiate(this, newTab.clss.getName(), newTab.args);
ft.add(R.id.realtabcontent, newTab.fragment, newTab.tag);
} else ft.attach(newTab.fragment);
}
mLastTab = newTab;
ft.commit();
this.getSupportFragmentManager().executePendingTransactions();
}
}
}
10 fragment onCreateView called many times 6 Android fragment OnCreateView called twice 9 NullPointerException due to 'void dalvik.system.CloseGuard.close()' in lollipop
So while debugging, I arrived to the conclusion that nothing works because onCreateView () is not actually called, even though my Fragment is on the screen. This happens after I rotated the device and I'm in landscape mode. If I report the device in portrait mode (from landscape to portrait again) and try to call that method, all is good.
Exactly, that's why the onActivityCreated () method isn't called. You create the Fragments after the Activity has been created. So it wouldn't make sense to call that method. Maybe you could use onAttach () instead. Click to expand... I didn't follow your line of thought, could you please re-elaborate?
Android Tabs with Fragments and ViewPager In android, we can create swipeable tabs layout using Swipe Views to switch between the tabs in the android application. The Swipe Views in android provides navigation between the sibling screens such as tabs with a horizontal finger gesture, sometimes it is called horizontal paging.
There a 3 ways to remove a Fragment from view:
hide
function on transaction object)detach
function on transaction object)remove
function on transaction object)If you hide it the view gets hidden, but is still in the layout and should stay intact. If you detach it, the view gets torn down, but the fragment is still managed by the FragmentManager (and will be recreated on a configuration change, for example). If you remove it it gets removed from the FragmentManager completely and it's state will no longer be managed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With