ActionBar选项卡中的片段无法访问活动

时间:2014-03-03 20:01:21

标签: android android-fragments android-actionbar

我已按照developer.android.com/guide/topics/ui/action.bar.html上的指南操作了操作栏中的标签。

在我的主要活动中,我添加了三个标签:

public class ToDoActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        actionBar.setDisplayShowTitleEnabled(false);

        Tab tab = actionBar.newTab().setText("Task List")
            .setTabListener(new TabListener<TaskListFragment>(
                    this, "task list", TaskListFragment.class));
        actionBar.addTab(tab);

        tab = actionBar.newTab().setText("Pie Chart")
            .setTabListener(new TabListener<TaskPieChartFragment>(
                    this, "pie chart", TaskPieChartFragment.class));
        actionBar.addTab(tab);

        tab = actionBar.newTab().setText("Task Map")
            .setTabListener(new TabListener<TaskMapFragment>(
                    this, "task map", TaskMapFragment.class));
        actionBar.addTab(tab);
    }
}

第一个标签的片段执行得很好。它可以查找视图并访问活动。单击导航中的第二个选项卡可显示片段(按预期),但不执行该片段的生命周期功能(onActivityCreated(),onStart(),onResume()等)。此外,每次从该片段调用getActivity()都会返回一个null对象。

public class TaskPieChartFragment extends Fragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_task_pie_chart, container, false);
    }

    public void updatePieChart() {
        TextView textView = (TextView) getActivity().findViewById(R.id.some_text);
        textView.setText("something something");
    }
}

布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/some_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

从TabListener中调用updatePieChart()函数:

public class TabListener<T extends Fragment> implements ActionBar.TabListener {

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        if (mFragment == null) {
            mFragment = Fragment.instantiate(mActivity,  mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
        } else {
            ft.attach(mFragment);
        }
        try {
            TaskPieChartFragment pieChartFragment = (TaskPieChartFragment) mFragment;
            pieChartFragment.updatePieChart();
        } catch (ClassCastException e) {
        // not the fragment we were looking for
        }
    }

}

每当我选择带有TaskPieChartFragment的标签时,我都会在updatePieChart()的第一行发出一个NullPointerException。为什么第二个片段与第一个片段的行为完全不同,我似乎无法获得对该活动的引用?

PS

我也试过传递TabListener中保存的活动。然后NullPointerException不是源于updatePieChart()中的第一行,而是第二行,因此活动无法找到该视图。

2 个答案:

答案 0 :(得分:0)

活动不拥有视图,所以它无法找到它并不奇怪。将getActivity()替换为getView(),您应该很高兴。 getView()为您提供此Fragment的根视图,并且应该能够找到您正在查找的视图,因为它是视图的祖先之一。您只能找到一个包含其祖先的视图,因为findViewWithId()会递归查看所有子项以查找视图。

答案 1 :(得分:0)

它崩溃的原因是因为FragmentTransaction尚未完成。

方法getActivity()仅返回片段回调onAttach()onDetach()之间的活动,而这只会在事务ft完成且框架通过所有事件后才会发生回调。

你可能应该在onResume()或其他一些Fragment生命周期回调中更新你的饼图。

修改

重新阅读代码,在您调用updatePieChart()时,尚未创建视图。所以也是这样。

作为一般规则,片段的视图应在实际片段内更新。

可能是这样的:

公共类TaskPieChartFragment扩展Fragment {

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_task_pie_chart, container, false);
}

public void onResume(){
    super.onResume();
    updatePieChart();
}

private void updatePieChart() {
    TextView textView = (TextView) getView().findViewById(R.id.some_text);
    textView.setText("something something");
}

}

这个想法是片段应该是自包含的实体,而不是依赖于调用它们进行更新的活动。