我正在使用ACL中的
这里就出现了问题。有时候
我被告知ACL中的
简短地说,我有一个自定义布局,用于处理长按布局事件,目的是创建一个包含有关单元格按下的实体信息的
这是我的自定义布局(也许有一种更容易获取
ViewPager
来展示一些Fragment
。一开始,这些Fragment都是ListFragment
,因为它们包含了一个列表。我想要模仿一个两列的表格,所以列表中的每个元素都包含着另外两个对象的列表。我希望每个单元格都可以长按(而不是整个列表项),因此我实现了自己的ColumnLayout(也许应该叫做CellLayout)。每个列表项包含了两个可长按的ColumnLayout,并实现了getContextMenuInfo()
方法来返回有关哪个实体被长按的信息。该方法查找ViewPager,请求当前Fragment,然后调用Fragment来返回从被长按的视图中获取的实体ID。为了获取正确的行,Fragment需要执行以下操作:getListView().getPositionForView(v)
这里就出现了问题。有时候
getListView()
会抛出IllegalStateException
,显示“内容视图尚未创建”。也就是说,onCreateView(...)
还没有被调用。这种情况只会在应用程序恢复时发生。今天我设法通过在Galaxy Nexus的“设置”>“开发者选项”中启用“不保留活动”选项来重现这个问题。我启动应用程序,按下Home键,然后从最近使用的应用程序菜单中重新打开应用程序,现在,如果我长按我的列表视图中的任何一个单元格,就会抛出这个异常。通过一些调试输出,我设法验证onCreateView从未被调用过。这有点奇怪,因为整个ViewPager以及它的Fragment、ListView和单元格项目都已经绘制好了!我被告知ACL中的
ListFragment
不支持自定义布局,所以我重新实现了我的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;
}
}
}
这里是 Fragment
的片段:
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和自定义布局所有都会被绘制,这不是很奇怪吗?然而,如果我长按listview中的任何单元格,就会得到IllegalStateException,提示视图尚未创建?
编辑/ 实际上,在onCreateView中输出Log.d(Constants.TAG, "onCreateView!!!!");显示该方法在第一次启动应用程序时调用两次(每个ViewPager的Fragment都调用一次),但在应用程序恢复时不再调用!这是一个bug还是我做错了什么?