[英]Android 2.1 NullPointerException with TabWidgets
我有一个无法解决的问题,它仅发生在运行<2.1的设备上。 它在android 2.2上工作正常。 我有一个异步任务,它在加载所有选项卡时显示一个加载对话框。 这是TabActivity的代码:
public class OppTabsView extends TabActivity {
Dialog dialog;
String errorText;
boolean save;
final int OPP_SAVE = 0;
public static boolean edited;
public void onCreate(Bundle icicle) {
try {
super.onCreate(icicle);
new DoInBackground().execute();
} catch (Exception e) {
Toast.makeText(this, "Error occured. Please try again later.",
Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onPause() {
super.onPause();
}
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, OPP_SAVE, 0, "Test");
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case OPP_SAVE:
save = true;
new DoInBackground().execute();
return true;
}
return false;
}
public void LoadOpp() {
handler.sendEmptyMessage(0);
}
public void SaveOpp() {
DoStuff();
}
public void LoadLayout() {
setContentView(R.layout.view_opptabs);
/* TabHost will have Tabs */
TabHost tabHost = (TabHost) findViewById(android.R.id.tabhost);
/*
* TabSpec used to create a new tab. By using TabSpec only we can able
* to setContent to the tab. By using TabSpec setIndicator() we can set
* name to tab.
*/
/* tid1 is firstTabSpec Id. Its used to access outside. */
TabSpec firstTabSpec = tabHost.newTabSpec("tid1");
TabSpec secondTabSpec = tabHost.newTabSpec("tid1");
TabSpec thirdTabSpec = tabHost.newTabSpec("tid1");
/* TabSpec setIndicator() is used to set name for the tab. */
/* TabSpec setContent() is used to set content for a particular tab. */
firstTabSpec.setIndicator("General",
getResources().getDrawable(R.drawable.tab_moneybag))
.setContent(new Intent(this, OppTabGeneral.class));
secondTabSpec.setIndicator("Details",
getResources().getDrawable(R.drawable.tab_papers)).setContent(
new Intent(this, OppTabDetails.class));
thirdTabSpec.setIndicator("Contact",
getResources().getDrawable(R.drawable.tab_contact)).setContent(
new Intent(this, OppTabContact.class));
/* Add tabSpec to the TabHost to display. */
tabHost.addTab(firstTabSpec);
tabHost.addTab(secondTabSpec);
tabHost.addTab(thirdTabSpec);
}
private void do_update() {
if (save) {
SaveOpp();
} else {
LoadOpp();
}
}
Handler handler = new Handler() {
public void handleMessage(Message msg) {
LoadLayout();
}
};
private class DoInBackground extends AsyncTask<Void, Void, Void> implements
DialogInterface.OnCancelListener {
protected void onPreExecute() {
String verb = "Connecting";
if (save) {
verb = "Saving";
}
dialog = ProgressDialog.show(OppTabsView.this, "", verb
+ ". Please Wait...", true, true, this);
}
protected Void doInBackground(Void... v) {
do_update();
return null;
}
protected void onPostExecute(Void v) {
dialog.dismiss();
}
public void onCancel(DialogInterface dialog) {
cancel(true);
dialog.dismiss();
finish();
}
}
}
这是错误的堆栈跟踪:
java.lang.NullPointerException
at android.widget.TabWidget.dispatchDraw(TabWidget.java:206)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at android.view.ViewGroup.drawChild(ViewGroup.java:1531)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.ViewGroup.drawChild(ViewGroup.java:1529)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1258)
at android.view.View.draw(View.java:6538)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1830)
at android.view.ViewRoot.draw(ViewRoot.java:1349)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1114)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
at dalvik.system.NativeStart.main(Native Method)
我试着逐步解决它,但是错误似乎是无处不在,而不是在特定的行。 任何帮助是极大的赞赏。
一个简单的办法是设置在你的布局tabWidget知名度水涨船高
<TabWidget
android:id="@android:id/tabs"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:visibility="gone" />
然后,一旦定义了标签内容,就可以再次使其可见:
// Add tab content (here a fragment class)
tabHost.addTab(
tabHost.newTabSpec("tag1").setIndicator("Title"),
contentFragment.class,
null);
// Set tabWidget visible again
tabWidget.setVisibility(View.VISIBLE);
TabSpec firstTabSpec = tabHost.newTabSpec("tid1");
TabSpec secondTabSpec = tabHost.newTabSpec("tid1");
TabSpec thirdTabSpec = tabHost.newTabSpec("tid1");
您是否可以将同一个“标签”用于多个TabSpec? 我会尝试正确设置这些设置,看看是否可以解决。
编辑:好的,所以我的建议没有解决,但无论如何要有唯一的标签还是有意义的。
试试这个看看是否有帮助。 在LoadLayout()方法的末尾添加一个选项以设置当前选定的选项卡,如下所示(请参阅最后一行)...
/* Add tabSpec to the TabHost to display. */
tabHost.addTab(firstTabSpec);
tabHost.addTab(secondTabSpec);
tabHost.addTab(thirdTabSpec);
tabHost.setCurrentTab(0); // <== Add this
EDIT2:我发现TabWidget.java源代码和第206行(发生NullPointerException的地方)是...
mBottomLeftStrip.setState(selectedChild.getDrawableState());
...我可以看到三种可能的异常原因。
selectedChild.getDrawableState()
的结果为null 最后一个似乎是可能的原因,但是我不确定是什么导致它返回null。
尝试使用Google搜索“ TabWidget.java源代码”-第二个结果指向grepcode.com,它具有行号,您可以在异常发生时看到它的操作。
从1.6和2.1的AsyncTask填充的选项卡也存在相同的问题。 看起来早期版本不喜欢没有任何选项卡的TabHost。 要解决此问题,我不使用TabActivity并在AsyncTask的onPostExecute函数中手动创建其所有层次结构的TabHost。
受相关的TabHost答案之一启发:
public class FixedTabHost extends FragmentTabHost
{
public FixedTabHost(Context context, AttributeSet attrs)
{
super(context, attrs);
}
@Override
protected void dispatchDraw(Canvas canvas)
{
try { super.dispatchDraw(canvas); }
catch (Exception ignored) {}
}
}
为我工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.