【问题标题】:Tabhost nullpointerexception when tabhost isn't the only thing in the layout当 tabhost 不是布局中唯一的东西时,Tabhost nullpointerexception
【发布时间】:2011-04-26 19:52:00
【问题描述】:

我注意到使用 tabhost 有很多问题,但没有一个真正适合我的问题。我正在尝试创建一个顶部带有action bar 的视图,然后是栏下方的一排选项卡。这是我的活动布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    style="@style/Dashboard">

    <com.ftni.common.ui.ActionBar
        android:id="@+id/actionbar"
        style="@style/ActionBar"/>

    <TabHost android:id="@android:id/tabhost"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:padding="5dp">
            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:padding="5dp" />
        </LinearLayout>
    </TabHost>
</LinearLayout>

接下来,我们将我的活动声明为这样

public class DashboardActivity extends TabActivity {

我正在像这样构建我的标签。

private void buildTabs()
{
    Resources res = getResources(); // Resource object to get Drawables
    TabHost tabHost = (TabHost)findViewById(android.R.id.tabhost);  // The activity TabHost
    TabHost.TabSpec spec;  // Resusable TabSpec for each tab
    Intent intent;  // Reusable Intent for each tab

    // Create an Intent to launch an Activity for the tab (to be reused)
    intent = new Intent().setClass(this, StatementsActivity.class);

    // Initialize a TabSpec for each tab and add it to the TabHost
    spec = tabHost.newTabSpec("statements").setIndicator("Statements",
                      res.getDrawable(R.drawable.ic_tab_active))
                  .setContent(intent);
    tabHost.addTab(spec);

    // Do the same for the other tabs
    intent = new Intent().setClass(this, PaymentsActivity.class);
    spec = tabHost.newTabSpec("payments").setIndicator("Payments",
                      res.getDrawable(R.drawable.ic_tab_active))
                  .setContent(intent);
    tabHost.addTab(spec);

    tabHost.setCurrentTab(0);
}

当我尝试使用getTabHost(); 时,它总是返回一个空值。所以,我切换到TabHost tabHost = (TabHost)findViewById(android.R.id.tabhost);,它不会返回一个空的tabhost,但是tabHost.addTab(spec);仍然会导致一个空指针异常。

这里是堆栈跟踪

04-26 19:50:12.494: ERROR/AndroidRuntime(7367): FATAL EXCEPTION: main
04-26 19:50:12.494: ERROR/AndroidRuntime(7367): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ftni.consumer/com.ftni.consumer.ui.DashboardActivity}: java.lang.NullPointerException
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1622)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1638)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at android.app.ActivityThread.access$1500(ActivityThread.java:117)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:928)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at android.os.Handler.dispatchMessage(Handler.java:99)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at android.os.Looper.loop(Looper.java:123)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at android.app.ActivityThread.main(ActivityThread.java:3647)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at java.lang.reflect.Method.invokeNative(Native Method)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at java.lang.reflect.Method.invoke(Method.java:507)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at dalvik.system.NativeStart.main(Native Method)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367): Caused by: java.lang.NullPointerException
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at android.widget.TabHost.addTab(TabHost.java:212)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at com.ftni.consumer.ui.DashboardActivity.buildTabs(DashboardActivity.java:75)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at com.ftni.consumer.ui.DashboardActivity.onCreate(DashboardActivity.java:29)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1586)
04-26 19:50:12.494: ERROR/AndroidRuntime(7367):     ... 11 more

第 75 行是第一个 tabHost.addTab(spec);

另外,我的所有活动都在我的清单中声明。

<activity android:name=".ui.DashboardActivity"></activity>
<activity android:name=".ui.StatementsActivity"></activity>
<activity android:name=".ui.PaymentsActivity"></activity>

编辑:

为了证明这不是问题,我删除了操作栏,将布局完全按照教程中的内容进行,但我仍然得到从 getTabHost(); 返回的空值

编辑 2: 为了清楚起见,完整的类代码

public class DashboardActivity extends TabActivity {
    private ProfileModel profile;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        profile = Controller.getProfile();

        setContentView(R.layout.dashboard);

        buildTabs();

        new LoadDashboardTask().execute();
    }

    @Override
    public void onContentChanged()
    {
        ActionBar actionBar = (ActionBar)findViewById(R.id.actionbar);
        if (actionBar != null)
        {
            actionBar.setOnTitleClickListener(new OnClickListener() {
                public void onClick(View v) {
                    //do nothing for now.  User is already "home"
                }
            });

            if(profile.Accounts.length == 1)
                actionBar.setTitle(profile.Accounts[0].Name);
            else
                actionBar.setTitle(profile.Name);

        }
    }

    private void buildTabs()
    {
        Resources res = getResources(); // Resource object to get Drawables
        TabHost tabHost = getTabHost();// The activity TabHost

        if(tabHost != null)
        {
            // Initialize a TabSpec for each tab and add it to the TabHost
            TabSpec statementSpec = tabHost.newTabSpec("statements").setIndicator("Statements",
                              res.getDrawable(R.drawable.ic_tabs_statements))
                          .setContent(new Intent().setClass(DashboardActivity.this, StatementsActivity.class));
            tabHost.addTab(statementSpec);

            TabSpec paymentSpec = tabHost.newTabSpec("payments").setIndicator("Payments",
                              res.getDrawable(R.drawable.ic_tabs_payments))
                          .setContent(new Intent().setClass(DashboardActivity.this, PaymentsActivity.class));
            tabHost.addTab(paymentSpec);

            tabHost.setCurrentTab(0);
        }
    }

    private class LoadDashboardTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected void onPreExecute()
        {
            ActionBar actionBar = (ActionBar)findViewById(R.id.actionbar);
            actionBar.setProgressBarVisibility(View.VISIBLE);
        }

        @Override
        protected Void doInBackground(Void... params) 
        {
            return null;
        }

        @Override
        protected void onPostExecute(Void result)
        {
            ActionBar actionBar = (ActionBar)findViewById(R.id.actionbar);
            actionBar.setProgressBarVisibility(View.GONE);
        }
    }
}

【问题讨论】:

标签: android nullpointerexception android-tabhost


【解决方案1】:

文档指出,如果使用 findViewById() 加载 TabHost,您应该“在添加选项卡之前调用 setup()。”,这就是您正在做的事情。见here。但是,既然您使用的是 TabActivity,为什么不调用 getTabHost() 而不是手动获取视图?

【讨论】:

  • 在我所说的 OP 中,当我调用 getTabHost() 时,会返回一个空值。
  • 顺便说一句,我尝试了使用 setup 的建议,然后错误地说我需要使用活动管理器,因为我没有从 TabActivity (我是)继承,然后错误Activities cannot be added until the containing group has been created .几乎就像整个事情都忽略了我的活动是从 TabActivity 扩展的事实。
  • 我之前已经实现了选项卡,但没有从 TabActivity 扩展,所以这是可行的。此外,文档指出 TabHost 必须是布局中的第一个元素,这可能是另一个问题(不用担心,它不会在您的操作栏之前呈现任何内容)。你什么时候调用 buildTabs,在 onCreate 的什么时候?
  • 我把我的整个班级都贴在上面了。我尝试将布局更改为仅选项卡主机(并删除所有操作栏代码),但仍然存在问题。
  • 我只是想指出,按照教程中的步骤,我使用文本视图创建了其他活动,我添加了状态列表可绘制对象,我什至测试了其中的两个活动确保它们工作的标签;他们是这样。我的 DashboardActivity 类存在根本性的问题,以至于它好像忽略了 TabActivity 继承。即使我进行了空检查并将选项卡托管在布局中的第一项,我仍然会从 TabActivity 类中获得空引用异常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多