Android 2.1 NullPointerException с TabWidgets - PullRequest
4 голосов
/ 17 февраля 2011

У меня есть проблема, которую я не смог выяснить, и это происходит только на устройствах с <2.1. Работает нормально на андроиде 2.2. У меня есть асинхронная задача, которая отображает диалоговое окно загрузки, в то время как он загружает все вкладки. Вот код для TabActivity: </p>

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)

Я попытался пройти через это, но, похоже, ошибка появляется не из-за чего-либо, а из определенной строки. Любая помощь с благодарностью.

Ответы [ 4 ]

1 голос
/ 26 февраля 2012

Была такая же проблема с вкладками, заполненными из AsyncTask на 1.6 и 2.1.Похоже, более ранние версии не любят TabHost без каких-либо вкладок.Чтобы решить эту проблему, я не использую TabActivity и создаю TabHost со всей его иерархией вручную в функции onPostExecute AsyncTask.

1 голос
/ 19 января 2013

Простое решение состоит в том, чтобы установить видимость 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);
1 голос
/ 17 февраля 2011
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());

... есть три возможные причины исключения, которое я вижу.

  1. mBottonLeftStrip имеет значение null (крайне маловероятно)
  2. selectedCHild имеет значение null (TabWidget должен по умолчанию иметь дочерний 0 и использование tabHost.setCurrentTab () привело бы к тому, что в любом случае)
  3. РезультатselectedChild.getDrawableState() равно нулю

Последнее, вероятно, является вероятной причиной, но я не уверен, что может привести к тому, что он вернет значение null.

Попробуйте Google для 'TabWidget.java source'- второй результат указывает на grepcode.com с номерами строк, и вы можете увидеть, что он пытается сделать в точке исключения.

0 голосов
/ 04 октября 2013

Вдохновлен одним из связанных ответов 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) {}
    }
}

работал для меня.

...