Removing tabs from tabhost causes app to crash

I need to be able to close tabs in a TabHost for an android app I'm working on. I am currently calling this code.

    tabHost.getTabWidget().removeViewAt(toDelete);

Open in new window


Where toDelete is the index of the tab that called the removal method. It looks like that code removes the tab, from the split second I can see it before it crashes. I'm thinking there's another removal method I need to call somewhere, because it appears to crash when attempting to draw the tab that was removed. I also tried

    tabHost.removeViewAt(toDelete);

Open in new window


But it crashed because it didn't have a view at toDelete, which is expected since (I think) it just contains the tab widget rather than the actual tabs.

Here are my crash logs

    04-04 16:05:53.149: E/AndroidRuntime(7885): FATAL EXCEPTION: main
    04-04 16:05:53.149: E/AndroidRuntime(7885): java.lang.NullPointerException
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2495)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.widget.TabWidget.dispatchDraw(TabWidget.java:323)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.View.draw(View.java:10981)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.widget.FrameLayout.draw(FrameLayout.java:450)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2126)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewRootImpl.draw(ViewRootImpl.java:2026)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1634)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.os.Handler.dispatchMessage(Handler.java:99)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.os.Looper.loop(Looper.java:137)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at android.app.ActivityThread.main(ActivityThread.java:4424)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at java.lang.reflect.Method.invokeNative(Native Method)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at java.lang.reflect.Method.invoke(Method.java:511)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    04-04 16:05:53.149: E/AndroidRuntime(7885): 	at dalvik.system.NativeStart.main(Native Method)

Open in new window


Any ideas on what other methods I should be calling? Or am I going down the entirely wrong path?

Edit: I just tried opening 5 tabs and closing the second one. It didn't crash at first, but it did have some VERY odd behavior. When I click on a tab, it shows the next one to the right as being highlighted, but displays the correct tab, until I click the last tab at which point the app crashes. A few screen shots in case it helps to describe my issue.

When I click the songs tab before closing a tab
Songs tab working
When I click the tab for a specific song before closing a tab
Lyrics tab working
When I click the songs tab after closing the current program tab. The correct contents are displayed but the wrong tab looks selected.
After closing a tab
Curtis LongAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

alexey_gusevCommented:
have you tried setting current tab to 0 before deleting?
0
Curtis LongAuthor Commented:
This is the entire code that is responsible for deleting the tab.

if(toDelete != -1)
{
	int currentTab = tabHost.getCurrentTab();
	if(currentTab >= toDelete)
		currentTab--;
	tabHost.setCurrentTab(0);
	tabHost.getTabWidget().removeViewAt(toDelete);
	int count = tabHost.getTabWidget().getTabCount()-1;
	while(currentTab > count)
		currentTab--;
	tabHost.setCurrentTab(currentTab);
	toDelete = -1;
}

Open in new window


I was able to find a solution, but I don't like it. As each tab is added, I save it to a Map, with the index of the tab as the key, and the TabHost.TabSpec as the value. Then this code runs when a tab is deleted

if(toDelete != -1)
{
	int currentTab = tabHost.getCurrentTab();
	tabs.remove(toDelete);
	tabHost.setCurrentTab(0);
	tabHost.clearAllTabs();
	Iterator<Entry<Integer, TabSpec>> it = tabs.entrySet().iterator();
	int counter = 0;
	while(it.hasNext())
	{
		@SuppressWarnings("rawtypes")
		Map.Entry pairs = (Map.Entry)it.next();
		TabHost.TabSpec spec = (TabSpec)pairs.getValue();
		tabHost.addTab(spec);
		if(counter != 0)
		{
			View view = getTabWidget().getChildTabViewAt(counter);
			view.setId((Integer)pairs.getKey());
			registerForContextMenu(view);
		}
		counter++;
	}
	int count = tabHost.getTabWidget().getTabCount()-1;
	while(currentTab > count)
		currentTab--;
	tabHost.setCurrentTab(currentTab);
	toDelete = -1;
}

Open in new window


I don't like having to delete all the tabs to close one tab though, and I'm still hoping there might be a better solution.
0
alexey_gusevCommented:
I don't like it either :) - but this seems to be the only one available
0
alexey_gusevCommented:
actually, looking at the source code (conveniently available now for API levels 14 & 15 right from SDK manager)  I guess you might use TabHost.getContentView() and then go from there.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Android

From novice to tech pro — start learning today.