Как получить представление об фрагменте вне OnCreateView ()

У меня есть Fragment с TableLayout . Данные в таблице взяты из SQLite db. SQLite db заполняется из веб- AsyncTask RESTful в AsyncTask в MainActivity . Fragment должен дождаться завершения задачи перед заполнением таблицы. Fragment прослушивает onPostExecute() метода onPostExecute() . Когда это так, вызывается метод onLoadAndStoreComplete() в Fragment . Все это работает.

Мне нужно получить представление о TableLayout вне метода OnCreateView() фрагмента. Если бы я мог получить представление о фрагменте в onLoadAndStoreComplete которое бы привело меня туда.

Тот же код, что и здесь. У меня есть mContext из MainActivity, но у него нет связанного с ним метода getView() .

Я пробовал:
– создание члена класса rootView и назначение в onCreateView (), но в onLoadAndStoreComplete() оно равно null.
– создание класса memberLayout класса и назначение в onCreateView (), но в onLoadAndStoreComplete() оно равно null.
– вызов this.getView () снова в onLoadAndStoreComplete() , но он возвращает null.
– вызов инфлятора внутри onLoadAndStoreComplete() , который работает, но тогда я не знаю, что использовать для контейнера в .inflate()

Я не понимаю, почему значения класса class rootView и tableLayout имеют значение null в 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)); } ... } 

Если я правильно понимаю ваш код, есть что-то не то, что ваш код не соблюдает жизненный цикл фрагмента или другой экземпляр фрагмента .

A. Проблема жизненного цикла

Android Framework ожидает, что ваш фрагмент создаст свой вид внутри onCreateView() . Вид становится доступным после того, как framework вызывает этот метод.

Возможно, ваш код вызывался onLoadAndStoreComplete() до onCreateView() , и это вызвало проблему.

Вам нужно извлечь метод для заполнения фактических представлений данными, так как он может иметь 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! ... } } } 

B. Разный отказ экземпляра

Это может произойти, когда вы работаете в двух разных экземплярах перед упомянутым фрагментом.

Сначала все будет выглядеть в порядке: onCreateView() вызываемый до onLoadAndStoreComplete() . Поэтому проверьте их:

  • Логический / отладочный конструктор по умолчанию вызывает ваш фрагмент. Вы ожидаете получить один звонок для вашего фрагмента во время создания / загрузки потока.
  • Проверьте, является ли объект, который вызвал onCreateView() , тем же самым объектом, который вызвал onLoadAndStoreComplete() , вы можете использовать System.identityHashCode(this) , получение разных значений в этих двух методах – плохой знак

Если это то, что происходит, причина, вероятно, скрыта чуть глубже, и без кода я не могу дать вам точных советов по этому поводу. Как вы создаете свой фрагмент? Через XML или вручную, затем добавляя через FragmentManager или через ViewPager?

getView() предоставляет rootView of Fragment, который возвращается из onCreatedView() . Поэтому, если onLoadAndStoreComplete() onCreatedView() до onCreatedView() (который не может вернуть ваш rootView), вы получаете значение null так как пока не создано никакого представления.


Я попытался вызвать getView() внутри onViewCreated() который НЕ равен null:

  @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 } } 

Из фрагмента кода, если поля rootView и tableLayout инициализируются после вызова onCreateView(..) , если оба поля после этого не установлены в null, то они должны быть не onLoadAndStoreComplete(..) нулю при вызове onLoadAndStoreComplete(..) .

Сказал, что, я думаю, вы вызываете этот метод в другом экземпляре вашего фрагмента. Просмотрите свой код активности и убедитесь, что вы используете один и тот же экземпляр из фрагмента все время.

Мне нужно получить представление о TableLayout вне метода OnCreateView () фрагмента. Если бы я мог получить представление о фрагменте в onLoadAndStoreComplete, которое бы привело меня туда.

Попробуйте изменить определение onLoadAndStoreComplete, чтобы получить представление, а затем передать его в виде фрагмента.

Вы уверены, что onLoadAndStoreComplete () вызывается после onCreateView ()? Единственная причина, по которой переменные экземпляра имеют значение null, заключается в том, что метод, который их инициализирует, не вызывается.

Я предлагаю вам позвонить в Log.d в onAttach, onDetach, onCreate, onCreateView, onStart, onStop, onLoadAndStoreComplete, чтобы увидеть, в каком порядке вызывается. После этого обновите свой вопрос с помощью вывода журнала, чтобы узнать, какая проблема может быть проблемой, и, возможно, я мог бы дать вам более краткий ответ.

Вы можете сделать несколько исправлений:

Если асинхронная задача вызывается до запуска фрагмента, тогда ваш callback onLoadAndStoreComplete может быть вызван перед onCreateView (и все ваши представления не завышены)

Вы можете выполнить asyncTask из onCreateView, но вам нужно отобразить загрузчика, чтобы сообщить пользователю, что приложение синхронизируется

Вы также можете использовать 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; } } } 

Вам нужно изменить таблицуLayout в ListView (внутри RelativeLayout?)