Search code examples
androidandroid-fragmentsandroid-listfragment

Retrieve ListFragment from FragmentTabHost


I have a FragmentActivity that displays a android.support.v4.app.FragmentTabHost. The tabs will be of type ListFragment. The ListFragment fragments will have an ArrayAdapter that use an AyncTask to get the data from a web service. The issue arises when I have to update the data in the ArrayAdapter. I cannot seem to get a reference to the ListFragment of the tabs in order to get a reference to the adapter and update the data. I would like to have the ListFragment update in the onPostExecute method of the AysncTask. Thanks in advance.

MyFragmentActivity :

public class MyFragmentActivity extends FragmentActivity {

private FragmentTabHost fTabHost;

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

    setContentView(R.layout.myLayout);

    fTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
    fTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);

    // Add Nearby Places
    fTabHost.addTab(fTabHost.newTabSpec("nearby").setIndicator("Nearby"),NearbyFragment.class, null);
    fTabHost.setCurrentTab(0);

}

@Override
protected void onStart() {
    super.onStart();
    new RetrievePlacesTask().execute(new PlacesAPIClient().getNearbyPlaces());
}

private class RetrievePlacesTask extends AsyncTask<String, Void, PlacesAPIResults> {

    public RetrievePlacesTask() {
        super();
    }

    // Other methods ....

    protected void onPostExecute(PlacesAPIResults results) {

        FragmentManager fragmentManager = getSupportFragmentManager();
        // This returns null, I believe because it FragmentTabHost is a View not a Fragment
        Fragment tabhost = fragmentManager.findFragmentById(android.R.id.tabhost);
        FragmentManager childManager = tabhost.getChildFragmentManager();
        ListFragment nearbyListFragment = (ListFragment) childManager.findFragmentByTag("nearby");

        // Get adapter and update data

    }
}

}

myLayout.xml :

<android.support.v4.app.FragmentTabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TabWidget
        android:id="@android:id/tabs"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0" />

    <FrameLayout
        android:id="@android:id/tabcontent"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="0" />

    <FrameLayout
        android:id="@+id/realtabcontent"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

NearbyFragment (ListFragment)

public class NearbyFragment extends ListFragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    PlaceArrayAdapter adapter = new PlaceArrayAdapter(inflater.getContext(),R.layout.place_list_item, new ArrayList<Place>());  
    setListAdapter(adapter);
    return super.onCreateView(inflater, container, savedInstanceState);
}

}


Solution

  • Not sure if there is a better solution out there. but this seemed to work for me. I created an interface IHelper which had a method getAdapter and had my MyFragmentActivity implement. In NearbyFragment, I had to override the onAttach method which takes an Activity which in my case is MyFragmentActivity and stored it as a member variable of NearbyFragment class. Doing this allows the NearbyFragment class to cast the Activity to an IHelper interface and call getAdapter.

    IHelper :

    @Override
    public interface IHelper {
        public PlaceArrayAdapter getAdapter();
    }
    

    Changed :

    public class MyFragmentActivity extends FragmentActivity
    

    ** To : **

    public class MyFragmentActivity extends FragmentActivity implements IHelper
    

    Implement the getAdapter method :

    public PlaceArrayAdapter getAdapter() {
       // Your codez
    }
    

    ** NearbyFragment : **

    public class NearbyFragment extends ListFragment {
    
        IHelper helper;
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            try {
                helper = (IHelper) activity;
            } catch(ClassCastException e) {
                throw new ClassCastException(activity.toString() + " must implement interface.");
            }
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            setListAdapter(helper.getAdapter());
            return super.onCreateView(inflater, container, savedInstanceState);
        }
    }