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



У меня есть Fragment с TableLayout. Данные в таблице взяты из базы данных SQLite. База данных SQLite заполняется из RESTful webservice в AsyncTask в MainActivity. Перед заполнением таблицы Fragment Необходимо дождаться завершения задачи. Fragment ожидает вызова метода task onPostExecute(). Когда это так, вызывается метод onLoadAndStoreComplete() в Fragment. Это все работает.



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



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



Я пробовал:

- создание члена класса rootView и назначение в onCreateView (), но в onLoadAndStoreComplete(), он равен null.

- создание члена класса tableLayout и назначение в onCreateView (), но в onLoadAndStoreComplete(), это null.

- звоню сюда.getView () снова в onLoadAndStoreComplete(), но возвращает 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));
}
...
}
605   6  

6 ответов:

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

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

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

Возможно, что ваш код вызвал 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. отказ другого экземпляра

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

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

  • конструктор Log / debug по умолчанию вызывает ваш фрагмент. Вы ожидая получить один вызов для вашего фрагмента во время потока create / load.
  • проверьте, является ли объект, который вызвал onCreateView(), точно таким же объектом, который вызвал onLoadAndStoreComplete(), Вы можете использовать System.identityHashCode(this), получение различных значений в рамках этих двух методов является плохим знаком
Если это то, что происходит, причина, вероятно, скрыта немного глубже, и без кода я не могу дать вам точный совет на этот счет. Как вы создаете свой фрагмент? Через XML или вручную, а затем добавление через FragmentManager или через Видоискатель?

getView() дает rootView фрагмента, который возвращается из onCreatedView(). Таким образом, если 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
        }
    }

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

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

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

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

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

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

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

Если асинхронная задача вызывается до запуска фрагмента, то ваш обратный вызов 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;
        }
    }

}

Вам нужно изменить свой tableLayout на ListView (внутри Относительный отказ?)

Comments

    Ничего не найдено.