onCreateView не вызывается с фрагментом в ViewPager

Я использую ViewPager из ACL, чтобы показать пару Fragment s. Сначала эти фрагменты содержат все ListFragment , поскольку они содержат список. Я пытаюсь имитировать таблицу из двух столбцов, поэтому каждый элемент в списке содержит еще один список из двух объектов. Я хочу, чтобы на каждую ячейку можно было долго нажимать (а не на весь элемент списка), поэтому я реализовал свой собственный ColumnLayout (возможно, его следует называть CellLayout). Каждый элемент списка содержит два ColumnLayout, на которые можно нажать и удерживать, и реализует getContextMenuInfo () для возврата информации о том, на каком объекте был выполнен долгий щелчок. Этот метод ищет ViewPager, запрашивает текущий фрагмент, а затем вызывает фрагмент для возврата идентификатора объекта из представления, которое было долгим щелчком. Чтобы получить правильную строку, фрагменту нужно сделать:

getListView().getPositionForView(v)

И вот здесь начинается проблема. Иногда getListView () выдает IllegalStateException , говоря: «Представление содержимого еще не создано». Т.е. onCreateView (...) не был вызван. Это случается только иногда, когда приложение возобновляется. Сегодня мне удалось воспроизвести проблему, включив опцию «Не сохранять действия» в «Настройки»> «Параметры разработчика» на моем Galaxy Nexus.Я запускаю приложение, нажимаю «Домой», а затем повторно открываю приложение из меню последних приложений, и теперь, если я долго нажимаю любую из ячеек в моем представлении списка, возникает это исключение. По некоторым выводам отладки мне удалось убедиться, что onCreateView никогда не вызывался. Что немного странно, потому что весь ViewPager с его фрагментом, его ListView и его элементы ячеек отрисовываются!

На # android-dev мне сказали, что ListFragment в ACL не поддерживает настраиваемые макеты, поэтому я повторно реализовал свой android.support.v4.app.Fragment без использования ListFragment , но это не помогло.

Краткое описание: У меня есть настраиваемый макет, который обрабатывает событие длительного нажатия макета с целью создания объекта MenuInfo , содержащего информацию об объектах в нажатой ячейке. Чтобы найти сущность, содержащуюся в макете, в конечном итоге вызывается listview.getPositionForView (View v) , иногда вызывая IllegalStateException .

Вот мой собственный макет (возможно, есть более простой способ получить ViewPager , чем копаться в иерархии представлений):

package org.remotestick;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.widget.LinearLayout;

public class ColumnLayout extends LinearLayout {

    public ColumnLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ColumnLayout(Context context) {
        super(context);
    }

    @Override
    protected ContextMenuInfo getContextMenuInfo() {
        int itemTypeId = getChildAt(0).getId();
        int positionTypeId = getId();
        View currentView = this;
        ViewPager viewPager = null;
        while(currentView.getParent() != null) {
            currentView = (View) currentView.getParent();
            if(currentView.getId() == R.id.pager) {
                viewPager = (ViewPager) currentView;
                break;
            } else if (currentView.getId() == R.id.rootLayout)
                break;
        }
        if(viewPager == null)
            return null;

        WorkspaceAdapter adapter = (WorkspaceAdapter) viewPager.getAdapter();
        Pair<Integer, Integer> itemIdAndListPosition = adapter.getItemIdFromWorkspace(viewPager.getCurrentItem(), this, itemTypeId, (positionTypeId == R.id.leftColumn));
        if(itemIdAndListPosition == null)
            return null;
        else
            return new MatrixAdaptableContextMenuInfo(itemTypeId, itemIdAndListPosition.first, itemIdAndListPosition.second);
    }

    public static class MatrixAdaptableContextMenuInfo implements ContextMenuInfo {

        public final int itemTypeId;
        public final Integer itemId;
        public final Integer positionInList;

        public MatrixAdaptableContextMenuInfo(int itemTypeId, Integer itemId, Integer positionInList) {
            this.itemTypeId = itemTypeId;
            this.itemId = itemId;
            this.positionInList = positionInList;
        }

    }
}

И вот (фрагмент) фрагмента ]:

public class EntityTableFragment extends Fragment implements TelldusEntityChangeListener {

    protected static final String ARG_TITLE = "title";

    protected MatrixAdapter mAdapter;
    protected ProgressViewer mProgressViewer;
    protected MatrixFilter mFilter;
    protected Handler mHandler = new Handler();
    protected RemoteStickData db;

    public boolean onAttach = false;
    public boolean onCreateView = false;

    private ListView listView;

    public static EntityTableFragment newInstance(String title) {
        EntityTableFragment f = new EntityTableFragment();

        Bundle args = new Bundle();
        args.putString(ARG_TITLE, title);
        f.setArguments(args);
        return f;
    }

    @Override
    public void onAttach(SupportActivity activity) {
        super.onAttach(activity);
        onAttach = true;
            try {
            mProgressViewer = (ProgressViewer) activity;
            mAdapter = new MatrixAdapter(getActivity(), mProgressViewer, new ArrayList<List<MatrixEntity>>(), null);
            TelldusLiveService.addListener(this);
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement ProgressViewer");
        }
        db = new RemoteStickData(getActivity());
    }

    @Override
    public void onDetach() {
        super.onDetach();
        TelldusLiveService.removeListener(this);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        listView.setAdapter(mAdapter);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.list, null);
        listView = (ListView) view.findViewById(R.id.list);
        return view;
    }

    @Override
    public String toString() {
        return getArguments().getString(ARG_TITLE);
    }

    public Pair<Integer, Integer> getIdAndPositionForView(View v, boolean isLeft) {
        if(listView == null)
            throw new IllegalStateException("Listview not yet created");
        int positionForView = listView.getPositionForView(v);
        if(isLeft)
            return new Pair<Integer, Integer>(mAdapter.getItem(positionForView).get(0).getId(), positionForView);
        else
            return new Pair<Integer, Integer>(mAdapter.getItem(positionForView).get(1).getId(), positionForView);
    }

Разве не странно, что при возобновлении работы приложения (если действие было уничтожено) отображается ViewPager с его фрагментами, его ListView и его пользовательские макеты. Тем не менее, я получаю IllegalStateException о том, что представление не было создано, если я долго нажимаю любую из ячеек в списке?

edit / Фактически, a Log.d (Константы.TAG, "onCreateView !!!!"); вывод в onCreateView показывает, что методы вызываются два раза при первом запуске приложения (по одному для каждого фрагмента в ViewPager), но затем больше никогда не вызывается, когда приложение возобновляется !? Это ошибка или что я делаю не так?

5
задан pakerfeldt 17 January 2012 в 12:40
поделиться