Solved

Removing tabs from tabhost causes app to crash

Posted on 2012-04-04
4
1,431 Views
Last Modified: 2012-04-10
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
0
Comment
Question by:HDM
  • 3
4 Comments
 
LVL 24

Expert Comment

by:alexey_gusev
ID: 37809926
have you tried setting current tab to 0 before deleting?
0
 

Author Comment

by:HDM
ID: 37813781
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
 
LVL 24

Expert Comment

by:alexey_gusev
ID: 37826673
I don't like it either :) - but this seems to be the only one available
0
 
LVL 24

Accepted Solution

by:
alexey_gusev earned 500 total points
ID: 37826879
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

Featured Post

Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The case of the missing phone talks about the way a small electronic gadget (the mobile phone) has penetrated into our lives and has made us addicted to it.
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
This video is in connection to the article "The case of a missing mobile phone (https://www.experts-exchange.com/articles/28474/The-Case-of-a-Missing-Mobile-Phone.html)". It will help one to understand clearly the steps to track a lost android phone.

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question