Android FragmentTabHost:NullPointerException:Drawable.setState(int[])在空对象引用上

Android FragmentTabHost:NullPointerException:Drawable.setState(int[])在空对象引用上,android,Android,作为一名Android程序员新手,我一直在努力学习如何设置一个简单的选项卡式UI。因为我认为这是当今的最佳实践,所以我决定将我的布局基于FragmentTabHost,因为我正在处理片段,我的主要活动也基于FragmentActivity(通过扩展AppCompativeActivity) 我的测试应用程序的结构如下:我有一个带有线性布局的主活动,其中包含一个片段,用于显示另一个布局文件中定义的不同选项卡。我扩展了Fragment以创建一个TabsFragment类,该类基于不同的布局使用Fra

作为一名Android程序员新手,我一直在努力学习如何设置一个简单的选项卡式UI。因为我认为这是当今的最佳实践,所以我决定将我的布局基于FragmentTabHost,因为我正在处理片段,我的主要活动也基于FragmentActivity(通过扩展AppCompativeActivity)

我的测试应用程序的结构如下:我有一个带有线性布局的主活动,其中包含一个片段,用于显示另一个布局文件中定义的不同选项卡。我扩展了Fragment以创建一个TabsFragment类,该类基于不同的布局使用FragmentTabHost实现这个选项卡UI。我希望有两个选项卡:一个显示名称列表,另一个仅显示文本(名称是通过我已经彻底测试过的类生成的)

我使用的文件如下所示:

MainActivity.java

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;

public class MainActivity extends AppCompatActivity {
    private String TAG = "MainActivity";
    private Toolbar appToolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d ( TAG, "onCreate: setting content view" );
        setContentView ( R.layout.activity_main );

        appToolbar = ( Toolbar ) findViewById ( R.id.toolbar );
        setSupportActionBar ( appToolbar );

        Log.d ( TAG, "onCreate finished")
    }

    @Override
    public boolean onCreateOptionsMenu ( Menu menu ) {
        appToolbar.inflateMenu ( R.menu.menu_actions );

        return ( true );
    }
}
TabsFragment.java

import android.app.ListFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTabHost;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.support.v4.app.FragmentTabHost;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.TabHost;

/**
 * Created by Joshua on 12/12/2016.
 */

public class TabsFragment extends Fragment implements TabHost.OnTabChangeListener {
    private String TAG = "TabsFragment";

    /* Fixed tags for the different tabs */
    public static final String OVERVIEW_TAB_TAG = "TAB_OVERVIEW";
    public static final String SEARCH_TAB_TAG = "TAB_SEARCH";

    /* Objects necessary to build activity views
     */
    private LayoutInflater mInflater; // Used for building View objects in memory from our XML-resources

    /* The views and other fragments our fragment will contain and helper variables for accessing them
     */
    private View mRoot; // A reference to the root vie of our fragment
    private FragmentTabHost mFragmentTabHost; // A reference to the tab host ( tab controlling ) view of our fragment
    private String labelOverviewTab = "Overview";
    private String labelSearchTab = "Searhc";

    private CustomListFragment overviewTabFragment;
    private TextFragment searchTabFragment;

    /* Other fragment bookkeeping variables
     */
    private String mCurrentTab; // Stores the tag of the currently visible tag

    /* Data and adapters for our views */
    private Persons personsInfo;
    private ListAdapter namesListAdapter;

    /* This method will get executed when the system wants to recreate our view
       i.e. when the user returns or enters our tabs interface
       It will return a reference to the root node of the views tree
     */
    @Override
    public View onCreateView ( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) {
        super.onCreateView ( inflater, container, savedInstanceState );
        Log.d ( TAG, "onCreateView: starting ..." );

        /* Create all the view objects we need in memory and make sure the references to them in our class are correct
        */
        mRoot = inflater.inflate ( R.layout.tabs_fragment, container, false );
        mFragmentTabHost = ( FragmentTabHost ) mRoot.findViewById ( android.R.id.tabhost );

        Log.d ( TAG, "onCreateView: layouts inflated ... Attempting FragmentTabHost setup: ..." );
        mFragmentTabHost.setup ( getContext ( ), getChildFragmentManager ( ), android.R.id.tabcontent );

        Log.d ( TAG, "onCreateView: setup finished without errors  ..." );

        /* Initialize the tab host and make sure it's aware of all the tabs it has to manage
        */
        TabHost.TabSpec overviewTabSpec = mFragmentTabHost.newTabSpec ( OVERVIEW_TAB_TAG );
        TabHost.TabSpec searchTabSpec = mFragmentTabHost.newTabSpec ( SEARCH_TAB_TAG );
        overviewTabSpec = overviewTabSpec.setContent ( R.id.overviewTab ).setIndicator ( labelOverviewTab );
        searchTabSpec = searchTabSpec.setContent ( R.id.searchTab ).setIndicator ( labelSearchTab );

        Log.d ( TAG, "onCreateView: created tab specs with TAG's " + overviewTabSpec.getTag ( ) + " & " + searchTabSpec.getTag ( ) );

        Persons personsInfo = new Persons ( );
        personsInfo.addPerson ( "Stanley", "Kubrick", 21 );
        personsInfo.addPerson ( "Steven", "Spielberg", 20 );
        personsInfo.addPerson ( "Quentin", "Tarantino", 18 );
        personsInfo.addPerson ( "Joel", "Coen", 24 );
        personsInfo.addPerson ( "Ethan", "Coen", 26 );

        Log.d ( TAG, "onCreateView: initialized data" );

        overviewTabFragment = new CustomListFragment ( );
        overviewTabFragment.setFragmentContext ( getContext( ) );
        overviewTabFragment.setDataSource ( personsInfo );

        searchTabFragment = new TextFragment ( );
        searchTabFragment.setUniqueTag ( "Search" );
        searchTabFragment.setTabText ( "Here you will be able to SEARCH" );

        Log.d ( TAG, "onCreateView: created fragments" );

        mCurrentTab = OVERVIEW_TAB_TAG;

        Log.d ( TAG, "onCreateView: set current tab variable to " + OVERVIEW_TAB_TAG );

        getFragmentManager ( ).beginTransaction ( ).add ( overviewTabFragment, OVERVIEW_TAB_TAG ).commit ( );
        mFragmentTabHost.addTab ( overviewTabSpec, CustomListFragment.class, null );
        mFragmentTabHost.addTab ( searchTabSpec, TextFragment.class, null );

        Log.d ( TAG, "onCreateView: added current tab to fragment manager and added tabs to FragmentTabHost" );

        mFragmentTabHost.setCurrentTabByTag ( mCurrentTab );

        Log.d ( TAG, "onCreateView: set current tab to " + mCurrentTab );

        /* Make sure this fragment will listen to the user slecting a new ta
        */
        Log.d ( TAG, "onCreateView: configuring tab host listener" );

        mFragmentTabHost.setOnTabChangedListener ( this );

        Log.d ( TAG, "onCreateView finished. Returning " + mRoot );

        return ( mRoot );
    }

    @Override
    public void onActivityCreated ( Bundle savedInstanceState ) {
        super.onActivityCreated(savedInstanceState);
        setRetainInstance(true);

        Log.d(TAG, "onActivityCreated finished" );
    }

    @Override
    public void onTabChanged ( String tabID ) {
        /* Get the fragment manager associated with the tab controlling fragment
         */
        Log.d ( TAG, tabID );
        FragmentManager fragmentManager = this.getFragmentManager ( );
        if ( fragmentManager.findFragmentByTag ( tabID ) == null && mCurrentTab.equals ( OVERVIEW_TAB_TAG ) ) {
            fragmentManager.beginTransaction ( ).replace ( android.R.id.tabcontent, searchTabFragment, SEARCH_TAB_TAG ).commit ( );
            mCurrentTab = SEARCH_TAB_TAG;
        } else if ( fragmentManager.findFragmentByTag ( tabID ) == null && mCurrentTab.equals ( SEARCH_TAB_TAG ) ) {
            fragmentManager.beginTransaction ( ).replace ( android.R.id.tabcontent, overviewTabFragment, OVERVIEW_TAB_TAG ).commit ( );
            mCurrentTab = OVERVIEW_TAB_TAG;
        }
    }
}
package com.joshuaindustries.tabtest;

import android.support.v4.app.ListFragment;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

/**
 * Created by Joshua on 18/12/2016.
 */

public class CustomListFragment extends ListFragment {
    String TAG = "CustomListFragment";

    Context fragmentContext;

    Persons persons;
    ArrayAdapter namesListAdapter;

    public void setFragmentContext ( Context fragmentContext ) {
        this.fragmentContext = fragmentContext;
    }

    public void setDataSource ( Persons persons ) {
        this.persons = persons;
        namesListAdapter = new ArrayAdapter ( fragmentContext, R.layout.tab_content_list, R.id.list_item_text_view, persons.getFirstNameArray ( ) );
        setListAdapter ( namesListAdapter );
    }

    @Override
    public void onListItemClick ( ListView listView, View itemView, int position, long id ) {
        Intent showDetails = new Intent ( fragmentContext, details.class );

        listView.getItemAtPosition ( position );
        persons.putFieldsInIntent ( showDetails, position );

        startActivity ( showDetails );
    }
}
package com.joshuaindustries.tabtest;

import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TextView;

/**
 * Created by Joshua on 15/12/2016.
 */

public class TextFragment extends Fragment {
    String TAG = "TextFragment";
    String UNIQUE_TAG;

    private String mTabText;

    private View mRoot;
    private TextView mTextView;

    public void setTabText ( String tabText ) {
        mTabText = tabText;
    }

    @Override
    public View onCreateView ( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) {
        /* Create all the view objects we need in memory and make sure the references to them in our class are correct
         */
        mRoot = inflater.inflate ( R.layout.tab_content, container, false );
        mTextView = ( TextView ) mRoot.findViewById ( R.id.tabTextView );
        mTextView.setText ( mTabText );

        return ( mRoot );
    }

    public void setUniqueTag ( String tag ) { UNIQUE_TAG = tag; }
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // this is really important in order to save the state across screen
        // configuration changes for example
        setRetainInstance(true);
    }
}
CustomListFragment.java

import android.app.ListFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTabHost;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.support.v4.app.FragmentTabHost;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.TabHost;

/**
 * Created by Joshua on 12/12/2016.
 */

public class TabsFragment extends Fragment implements TabHost.OnTabChangeListener {
    private String TAG = "TabsFragment";

    /* Fixed tags for the different tabs */
    public static final String OVERVIEW_TAB_TAG = "TAB_OVERVIEW";
    public static final String SEARCH_TAB_TAG = "TAB_SEARCH";

    /* Objects necessary to build activity views
     */
    private LayoutInflater mInflater; // Used for building View objects in memory from our XML-resources

    /* The views and other fragments our fragment will contain and helper variables for accessing them
     */
    private View mRoot; // A reference to the root vie of our fragment
    private FragmentTabHost mFragmentTabHost; // A reference to the tab host ( tab controlling ) view of our fragment
    private String labelOverviewTab = "Overview";
    private String labelSearchTab = "Searhc";

    private CustomListFragment overviewTabFragment;
    private TextFragment searchTabFragment;

    /* Other fragment bookkeeping variables
     */
    private String mCurrentTab; // Stores the tag of the currently visible tag

    /* Data and adapters for our views */
    private Persons personsInfo;
    private ListAdapter namesListAdapter;

    /* This method will get executed when the system wants to recreate our view
       i.e. when the user returns or enters our tabs interface
       It will return a reference to the root node of the views tree
     */
    @Override
    public View onCreateView ( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) {
        super.onCreateView ( inflater, container, savedInstanceState );
        Log.d ( TAG, "onCreateView: starting ..." );

        /* Create all the view objects we need in memory and make sure the references to them in our class are correct
        */
        mRoot = inflater.inflate ( R.layout.tabs_fragment, container, false );
        mFragmentTabHost = ( FragmentTabHost ) mRoot.findViewById ( android.R.id.tabhost );

        Log.d ( TAG, "onCreateView: layouts inflated ... Attempting FragmentTabHost setup: ..." );
        mFragmentTabHost.setup ( getContext ( ), getChildFragmentManager ( ), android.R.id.tabcontent );

        Log.d ( TAG, "onCreateView: setup finished without errors  ..." );

        /* Initialize the tab host and make sure it's aware of all the tabs it has to manage
        */
        TabHost.TabSpec overviewTabSpec = mFragmentTabHost.newTabSpec ( OVERVIEW_TAB_TAG );
        TabHost.TabSpec searchTabSpec = mFragmentTabHost.newTabSpec ( SEARCH_TAB_TAG );
        overviewTabSpec = overviewTabSpec.setContent ( R.id.overviewTab ).setIndicator ( labelOverviewTab );
        searchTabSpec = searchTabSpec.setContent ( R.id.searchTab ).setIndicator ( labelSearchTab );

        Log.d ( TAG, "onCreateView: created tab specs with TAG's " + overviewTabSpec.getTag ( ) + " & " + searchTabSpec.getTag ( ) );

        Persons personsInfo = new Persons ( );
        personsInfo.addPerson ( "Stanley", "Kubrick", 21 );
        personsInfo.addPerson ( "Steven", "Spielberg", 20 );
        personsInfo.addPerson ( "Quentin", "Tarantino", 18 );
        personsInfo.addPerson ( "Joel", "Coen", 24 );
        personsInfo.addPerson ( "Ethan", "Coen", 26 );

        Log.d ( TAG, "onCreateView: initialized data" );

        overviewTabFragment = new CustomListFragment ( );
        overviewTabFragment.setFragmentContext ( getContext( ) );
        overviewTabFragment.setDataSource ( personsInfo );

        searchTabFragment = new TextFragment ( );
        searchTabFragment.setUniqueTag ( "Search" );
        searchTabFragment.setTabText ( "Here you will be able to SEARCH" );

        Log.d ( TAG, "onCreateView: created fragments" );

        mCurrentTab = OVERVIEW_TAB_TAG;

        Log.d ( TAG, "onCreateView: set current tab variable to " + OVERVIEW_TAB_TAG );

        getFragmentManager ( ).beginTransaction ( ).add ( overviewTabFragment, OVERVIEW_TAB_TAG ).commit ( );
        mFragmentTabHost.addTab ( overviewTabSpec, CustomListFragment.class, null );
        mFragmentTabHost.addTab ( searchTabSpec, TextFragment.class, null );

        Log.d ( TAG, "onCreateView: added current tab to fragment manager and added tabs to FragmentTabHost" );

        mFragmentTabHost.setCurrentTabByTag ( mCurrentTab );

        Log.d ( TAG, "onCreateView: set current tab to " + mCurrentTab );

        /* Make sure this fragment will listen to the user slecting a new ta
        */
        Log.d ( TAG, "onCreateView: configuring tab host listener" );

        mFragmentTabHost.setOnTabChangedListener ( this );

        Log.d ( TAG, "onCreateView finished. Returning " + mRoot );

        return ( mRoot );
    }

    @Override
    public void onActivityCreated ( Bundle savedInstanceState ) {
        super.onActivityCreated(savedInstanceState);
        setRetainInstance(true);

        Log.d(TAG, "onActivityCreated finished" );
    }

    @Override
    public void onTabChanged ( String tabID ) {
        /* Get the fragment manager associated with the tab controlling fragment
         */
        Log.d ( TAG, tabID );
        FragmentManager fragmentManager = this.getFragmentManager ( );
        if ( fragmentManager.findFragmentByTag ( tabID ) == null && mCurrentTab.equals ( OVERVIEW_TAB_TAG ) ) {
            fragmentManager.beginTransaction ( ).replace ( android.R.id.tabcontent, searchTabFragment, SEARCH_TAB_TAG ).commit ( );
            mCurrentTab = SEARCH_TAB_TAG;
        } else if ( fragmentManager.findFragmentByTag ( tabID ) == null && mCurrentTab.equals ( SEARCH_TAB_TAG ) ) {
            fragmentManager.beginTransaction ( ).replace ( android.R.id.tabcontent, overviewTabFragment, OVERVIEW_TAB_TAG ).commit ( );
            mCurrentTab = OVERVIEW_TAB_TAG;
        }
    }
}
package com.joshuaindustries.tabtest;

import android.support.v4.app.ListFragment;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

/**
 * Created by Joshua on 18/12/2016.
 */

public class CustomListFragment extends ListFragment {
    String TAG = "CustomListFragment";

    Context fragmentContext;

    Persons persons;
    ArrayAdapter namesListAdapter;

    public void setFragmentContext ( Context fragmentContext ) {
        this.fragmentContext = fragmentContext;
    }

    public void setDataSource ( Persons persons ) {
        this.persons = persons;
        namesListAdapter = new ArrayAdapter ( fragmentContext, R.layout.tab_content_list, R.id.list_item_text_view, persons.getFirstNameArray ( ) );
        setListAdapter ( namesListAdapter );
    }

    @Override
    public void onListItemClick ( ListView listView, View itemView, int position, long id ) {
        Intent showDetails = new Intent ( fragmentContext, details.class );

        listView.getItemAtPosition ( position );
        persons.putFieldsInIntent ( showDetails, position );

        startActivity ( showDetails );
    }
}
package com.joshuaindustries.tabtest;

import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TextView;

/**
 * Created by Joshua on 15/12/2016.
 */

public class TextFragment extends Fragment {
    String TAG = "TextFragment";
    String UNIQUE_TAG;

    private String mTabText;

    private View mRoot;
    private TextView mTextView;

    public void setTabText ( String tabText ) {
        mTabText = tabText;
    }

    @Override
    public View onCreateView ( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) {
        /* Create all the view objects we need in memory and make sure the references to them in our class are correct
         */
        mRoot = inflater.inflate ( R.layout.tab_content, container, false );
        mTextView = ( TextView ) mRoot.findViewById ( R.id.tabTextView );
        mTextView.setText ( mTabText );

        return ( mRoot );
    }

    public void setUniqueTag ( String tag ) { UNIQUE_TAG = tag; }
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // this is really important in order to save the state across screen
        // configuration changes for example
        setRetainInstance(true);
    }
}
TextFragment.java

import android.app.ListFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTabHost;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.support.v4.app.FragmentTabHost;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.TabHost;

/**
 * Created by Joshua on 12/12/2016.
 */

public class TabsFragment extends Fragment implements TabHost.OnTabChangeListener {
    private String TAG = "TabsFragment";

    /* Fixed tags for the different tabs */
    public static final String OVERVIEW_TAB_TAG = "TAB_OVERVIEW";
    public static final String SEARCH_TAB_TAG = "TAB_SEARCH";

    /* Objects necessary to build activity views
     */
    private LayoutInflater mInflater; // Used for building View objects in memory from our XML-resources

    /* The views and other fragments our fragment will contain and helper variables for accessing them
     */
    private View mRoot; // A reference to the root vie of our fragment
    private FragmentTabHost mFragmentTabHost; // A reference to the tab host ( tab controlling ) view of our fragment
    private String labelOverviewTab = "Overview";
    private String labelSearchTab = "Searhc";

    private CustomListFragment overviewTabFragment;
    private TextFragment searchTabFragment;

    /* Other fragment bookkeeping variables
     */
    private String mCurrentTab; // Stores the tag of the currently visible tag

    /* Data and adapters for our views */
    private Persons personsInfo;
    private ListAdapter namesListAdapter;

    /* This method will get executed when the system wants to recreate our view
       i.e. when the user returns or enters our tabs interface
       It will return a reference to the root node of the views tree
     */
    @Override
    public View onCreateView ( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) {
        super.onCreateView ( inflater, container, savedInstanceState );
        Log.d ( TAG, "onCreateView: starting ..." );

        /* Create all the view objects we need in memory and make sure the references to them in our class are correct
        */
        mRoot = inflater.inflate ( R.layout.tabs_fragment, container, false );
        mFragmentTabHost = ( FragmentTabHost ) mRoot.findViewById ( android.R.id.tabhost );

        Log.d ( TAG, "onCreateView: layouts inflated ... Attempting FragmentTabHost setup: ..." );
        mFragmentTabHost.setup ( getContext ( ), getChildFragmentManager ( ), android.R.id.tabcontent );

        Log.d ( TAG, "onCreateView: setup finished without errors  ..." );

        /* Initialize the tab host and make sure it's aware of all the tabs it has to manage
        */
        TabHost.TabSpec overviewTabSpec = mFragmentTabHost.newTabSpec ( OVERVIEW_TAB_TAG );
        TabHost.TabSpec searchTabSpec = mFragmentTabHost.newTabSpec ( SEARCH_TAB_TAG );
        overviewTabSpec = overviewTabSpec.setContent ( R.id.overviewTab ).setIndicator ( labelOverviewTab );
        searchTabSpec = searchTabSpec.setContent ( R.id.searchTab ).setIndicator ( labelSearchTab );

        Log.d ( TAG, "onCreateView: created tab specs with TAG's " + overviewTabSpec.getTag ( ) + " & " + searchTabSpec.getTag ( ) );

        Persons personsInfo = new Persons ( );
        personsInfo.addPerson ( "Stanley", "Kubrick", 21 );
        personsInfo.addPerson ( "Steven", "Spielberg", 20 );
        personsInfo.addPerson ( "Quentin", "Tarantino", 18 );
        personsInfo.addPerson ( "Joel", "Coen", 24 );
        personsInfo.addPerson ( "Ethan", "Coen", 26 );

        Log.d ( TAG, "onCreateView: initialized data" );

        overviewTabFragment = new CustomListFragment ( );
        overviewTabFragment.setFragmentContext ( getContext( ) );
        overviewTabFragment.setDataSource ( personsInfo );

        searchTabFragment = new TextFragment ( );
        searchTabFragment.setUniqueTag ( "Search" );
        searchTabFragment.setTabText ( "Here you will be able to SEARCH" );

        Log.d ( TAG, "onCreateView: created fragments" );

        mCurrentTab = OVERVIEW_TAB_TAG;

        Log.d ( TAG, "onCreateView: set current tab variable to " + OVERVIEW_TAB_TAG );

        getFragmentManager ( ).beginTransaction ( ).add ( overviewTabFragment, OVERVIEW_TAB_TAG ).commit ( );
        mFragmentTabHost.addTab ( overviewTabSpec, CustomListFragment.class, null );
        mFragmentTabHost.addTab ( searchTabSpec, TextFragment.class, null );

        Log.d ( TAG, "onCreateView: added current tab to fragment manager and added tabs to FragmentTabHost" );

        mFragmentTabHost.setCurrentTabByTag ( mCurrentTab );

        Log.d ( TAG, "onCreateView: set current tab to " + mCurrentTab );

        /* Make sure this fragment will listen to the user slecting a new ta
        */
        Log.d ( TAG, "onCreateView: configuring tab host listener" );

        mFragmentTabHost.setOnTabChangedListener ( this );

        Log.d ( TAG, "onCreateView finished. Returning " + mRoot );

        return ( mRoot );
    }

    @Override
    public void onActivityCreated ( Bundle savedInstanceState ) {
        super.onActivityCreated(savedInstanceState);
        setRetainInstance(true);

        Log.d(TAG, "onActivityCreated finished" );
    }

    @Override
    public void onTabChanged ( String tabID ) {
        /* Get the fragment manager associated with the tab controlling fragment
         */
        Log.d ( TAG, tabID );
        FragmentManager fragmentManager = this.getFragmentManager ( );
        if ( fragmentManager.findFragmentByTag ( tabID ) == null && mCurrentTab.equals ( OVERVIEW_TAB_TAG ) ) {
            fragmentManager.beginTransaction ( ).replace ( android.R.id.tabcontent, searchTabFragment, SEARCH_TAB_TAG ).commit ( );
            mCurrentTab = SEARCH_TAB_TAG;
        } else if ( fragmentManager.findFragmentByTag ( tabID ) == null && mCurrentTab.equals ( SEARCH_TAB_TAG ) ) {
            fragmentManager.beginTransaction ( ).replace ( android.R.id.tabcontent, overviewTabFragment, OVERVIEW_TAB_TAG ).commit ( );
            mCurrentTab = OVERVIEW_TAB_TAG;
        }
    }
}
package com.joshuaindustries.tabtest;

import android.support.v4.app.ListFragment;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

/**
 * Created by Joshua on 18/12/2016.
 */

public class CustomListFragment extends ListFragment {
    String TAG = "CustomListFragment";

    Context fragmentContext;

    Persons persons;
    ArrayAdapter namesListAdapter;

    public void setFragmentContext ( Context fragmentContext ) {
        this.fragmentContext = fragmentContext;
    }

    public void setDataSource ( Persons persons ) {
        this.persons = persons;
        namesListAdapter = new ArrayAdapter ( fragmentContext, R.layout.tab_content_list, R.id.list_item_text_view, persons.getFirstNameArray ( ) );
        setListAdapter ( namesListAdapter );
    }

    @Override
    public void onListItemClick ( ListView listView, View itemView, int position, long id ) {
        Intent showDetails = new Intent ( fragmentContext, details.class );

        listView.getItemAtPosition ( position );
        persons.putFieldsInIntent ( showDetails, position );

        startActivity ( showDetails );
    }
}
package com.joshuaindustries.tabtest;

import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TextView;

/**
 * Created by Joshua on 15/12/2016.
 */

public class TextFragment extends Fragment {
    String TAG = "TextFragment";
    String UNIQUE_TAG;

    private String mTabText;

    private View mRoot;
    private TextView mTextView;

    public void setTabText ( String tabText ) {
        mTabText = tabText;
    }

    @Override
    public View onCreateView ( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) {
        /* Create all the view objects we need in memory and make sure the references to them in our class are correct
         */
        mRoot = inflater.inflate ( R.layout.tab_content, container, false );
        mTextView = ( TextView ) mRoot.findViewById ( R.id.tabTextView );
        mTextView.setText ( mTabText );

        return ( mRoot );
    }

    public void setUniqueTag ( String tag ) { UNIQUE_TAG = tag; }
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // this is really important in order to save the state across screen
        // configuration changes for example
        setRetainInstance(true);
    }
}
Persons.java

package com.joshuaindustries.tabtest;

import android.content.Intent;

import java.util.ArrayList;

/**
 * Created by Joshua on 17/12/2016.
 */

public class Persons {
    public final static String PERSON_FIRST_NAME = "PERSON_FIRST_NAME";
    public final static String PERSON_LAST_NAME = "PERSON_LAST_NAME";
    public final static String PERSON_AGE = "PERSON_AGE";

    public class Person {
        String firstName;
        String lastName;
        int age;

        public Person ( String firstName, String lastName, int age ) {
            this.firstName = firstName; this.lastName = lastName; this.age = age;
        }

        public void setFirstName ( String newFirstName ) { firstName = newFirstName; }
        public void setLastName ( String newLastName ) { lastName = newLastName; }
        public void setAge ( int newAge ) { age = newAge; }

        public String getFirstName ( ) { return ( firstName ); }
        public String getLastName ( ) { return ( lastName ); }
        public int getAge ( ) { return ( age ); }
    }

    ArrayList<Person> listOfPersons;

    public Persons ( ) {
        listOfPersons = new ArrayList<Person> ( );
    }

    public void addPerson ( String firstName, String lastName, int age ) { listOfPersons.add ( new Person ( firstName, lastName, age ) ); }

    public String[] getFirstNameArray ( ) {
        String[] firstNamesArray = new String [ listOfPersons.size ( ) ];
        int index = 0;

        for ( Person person : listOfPersons ) {
            firstNamesArray [ index ] = person.getFirstName ( );
            ++ index;
        }

        return ( firstNamesArray );
    }

    public void putFieldsInIntent ( Intent intent, int position ) {
        Person personAskedFor = listOfPersons.get ( position );
        intent.putExtra ( PERSON_FIRST_NAME, personAskedFor.getFirstName ( ) );
        intent.putExtra ( PERSON_LAST_NAME, personAskedFor.getLastName ( ) );
        intent.putExtra ( PERSON_AGE, personAskedFor.getAge ( ) );
    }
}
我完全不知道是什么导致了这个NullPointerException,因为我已经确认我所有的布局都正确地膨胀了,我在网上其他地方找不到有类似问题的人。我非常感谢你的帮助,特别是如果你能解释为什么我做的是错的

提前感谢,,
Joshua通过删除TabWidget中的android:tabStripEnabled=“true”解决了问题,通过删除TabWidget中的android:tabStripEnabled=“true”解决了问题。感谢您的快速响应,这可能是重复的,但我已经查看并尝试了该问题中的建议,但没有效果,你找到解决办法了吗?我得到同样的错误,但只有一个索尼xperia x设备。它可以在所有其他设备上正常工作,包括其他索尼设备。无法找出问题的根源。您可能想了解如何创建一个。可能重复的。感谢您的快速响应,但我已经查看并尝试了该问题中的建议,但没有结果。我,您找到任何解决方案了吗?我得到同样的错误,但只有一个索尼xperia x设备。它可以在所有其他设备上正常工作,包括其他索尼设备。无法找出问题的根源。您可能想了解如何创建一个。哇-很高兴您发现这样一个虚幻的消息,非常感谢!!哇-很高兴你发现了这样一条虚幻的信息,非常感谢!!