如何获取OnCreateView()之外的片段视图

时间:2015-04-13 14:28:07

标签: android android-fragments

我有Fragment TableLayout。表中的数据来自SQLite数据库。 SQLite数据库是从AsyncTask中的MainActivity中的RESTful Web服务填充的。在填充表之前,Fragment必须等待任务完成。 Fragment侦听要调用的任务onPostExecute()方法。如果是,则调用onLoadAndStoreComplete()中的方法Fragment。一切正常。

我需要在片段的TableLayout方法之外查看OnCreateView()。如果我能够在onLoadAndStoreComplete中获得可以让我到那里的片段视图。

Same code as here. 我从MainActivity获得mContext,但没有与之关联的getView()方法。

我试过了:
- 在onCreateView()中创建类成员rootView并进行分配,但在onLoadAndStoreComplete()中,它为null。
- 创建一个类成员tableLayout并在onCreateView()中进行分配,但在onLoadAndStoreComplete()中,它为null。
- 在onLoadAndStoreComplete()中再次调用this.getView(),但它返回null - 在onLoadAndStoreComplete()内调用充气机,这有效,但后来我不知道在.inflate()电话中使用容器的内容

我不明白为什么rootView和tableLayout的类成员值在onLoadAndStoreComplete()

中为空
public class MyFragment extends Fragment implements OnLoadAndStoreCompleteListener {

private TableLayout tableLayout;
private View rootView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {
        mContext = this.getActivity();
        rootView = inflater.inflate(R.layout.fragment_permits, container, false); // this works
        tableLayout = (TableLayout) rootView.findViewById(R.id.main_table); // and this
        ...
    }

    @Override
    public void onLoadAndStoreComplete() {

       // rootView is null, ie not remembered from OnCreateView

        View view =  getView(); // null

        LayoutInflater inflater = LayoutInflater.from(getActivity());
      rootView = inflater.inflate(R.layout.fragment_permits, container, false); // container? don't know what it should be

        // tableLayout is null
        tableLayout.addView(tableRow, new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
    }
    ...
}

6 个答案:

答案 0 :(得分:6)

getView()给出了从onCreatedView()返回的片段的rootView。因此,如果在onLoadAndStoreComplete()完成之前调用onCreatedView()(它无法返回您的rootView),则会获得null,因为尚未创建视图。


我尝试在getView()内调用onViewCreated(),这是非空的:

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        View viewer=getView();
        if(viewer==null){
            Itu.showToast("null",getActivity(), Toast.LENGTH_LONG);
        }else{
            Itu.showToast(viewer.toString(),getActivity(), Toast.LENGTH_LONG);//This is called
        }
    }

答案 1 :(得分:6)

如果我正确理解了您的代码,那么您的代码不尊重Fragment生命周期不同的Fragment实例失败会出现问题。

:一种。生命周期问题

Android框架希望您的Fragment在Activity方法中创建其视图。 框架调用此方法后,视图可用。

您的代码可能在onCreateView()之前调用onLoadAndStoreComplete(),这导致了问题。

您需要提取用数据填充实际视图的方法,因为它可以有2个入口点。请参阅以下代码:

onCreateView()

<强> B中。不同的实例失败

当您在前面提到的片段的2个不同实例上进行操作时,可能会发生这种情况。

首先,所有内容都会按顺序查看:public class MyFragment extends Fragment implements OnLoadAndStoreCompleteListener { private TableLayout tableLayout; private View rootView; private SomeDataClass loadedData; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mContext = this.getActivity(); rootView = inflater.inflate(R.layout.fragment_permits, container, false); tableLayout = (TableLayout) rootView.findViewById(R.id.main_table); updateUi(); // If onLoadAndStoreComplete() was already called // this will plug newly created view to returned data } @Override public void onLoadAndStoreComplete() { loadedData = ...; // Save loaded data here updateUi(); // If onCreateView() was already called // this will plug loaded data to the view } private void updateUi() { if (rootView == null) { // Check if view is already inflated return; } if (loadedData != null) { // View is already inflated and data is ready - update the view! ... } } } onCreateView()之前调用。因此,请检查以下内容:

  • 记录/调试Fragment的默认构造函数调用。您希望在创建/加载流程期间对您的片段进行一次调用。
  • 检查调用onLoadAndStoreComplete()的对象是否与调用onCreateView()完全相同的对象,您可以使用onLoadAndStoreComplete(),在这两种方法中获取不同的值是一个不好的信号

如果发生这种情况,原因可能隐藏得更深一些,没有代码,我无法就此提供准确的建议。你如何创建你的片段?通过XML或手动然后通过FragmentManager或ViewPager添加?

答案 2 :(得分:2)

在您的代码片段中,如果在调用rootView后初始化字段tableLayoutonCreateView(..),如果之后两个字段都未设置为null,则在调用时它们必须不为null onLoadAndStoreComplete(..)

说,我认为你在片段的不同实例中调用该方法。查看您的活动代码,并检查您是否始终使用片段中的相同实例。

答案 3 :(得分:1)

  

我需要在OnCreateView()之外获得一个TableLayout的视图   片段的方法。如果我能得到片段的视图   onLoadAndStoreComplete会让我在那里。

尝试更改onLoadAndStoreComplete的定义以获取视图,然后传入片段视图。

答案 4 :(得分:1)

您确定在onCreateView()之后调用onLoadAndStoreComplete()吗?实例变量为null的唯一原因是没有调用初始化它们的方法。

我建议您在onAttach,onDetach,onCreate,onCreateView,onStart,onStop,onLoadAndStoreComplete上调用Log.d,以查看调用的顺序。在那之后,用日志输出更新你的问题,看看哪个可能是问题,我可能会给你一个更简洁的答案。

答案 5 :(得分:1)

您可以进行多项修复:

如果在启动片段之前调用异步任务,则可以在onCreateView(以及所有视图未膨胀)之前调用回调onLoadAndStoreComplete

你可以从onCreateView执行asyncTask,但你必须显示一个加载器来告诉用户应用程序正在同步

您也可以使用listview而不是tableLayout:

public class MyFragment extends Fragment implements OnLoadAndStoreCompleteListener {

private ListView listView;
private View rootView;
private MyAdapter adapter;
private List<T> mDatas; /// This one is populated like you want, from onLoadAndStoreComplete

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {
    mContext = this.getActivity();
    rootView = inflater.inflate(R.layout.fragment_permits, container, false); // this works
    listView = (ListView) rootView.findViewById(R.id.main_table); // and this
    mDatas = new List<>();
    adapter = new MyAdapter();
    tableLayout.setAdapter(adapter);
}

@Override
public void onLoadAndStoreComplete() {

   adapter.notifyDataSetChanged();
}


private class MyAdapter extends BaseAdapter{

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return mDatas.size() == 0 ? 1 : mDatas.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (mDatas.size()==0){
            // inflate new view with only a progressbar indefinite 
           LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
           convertView = inflater.inflate(R.layout.row_loading, parent, false);
           return convertView;
        }
        else{
             // list is populated
           LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
           convertView = inflater.inflate(R.layout.row_datas, parent, false);
           // do inflating view stuff
           return convertView;
        }
    }

}

您需要将tableLayout修改为ListView(在RelativeLayout内部吗?)