0

我有一个 ListFragment 为其元素提供 ContextMenu。当我将此片段放在 xml 布局中时,一切正常,但是当我通过 FragmentManager 以编程方式添加此 ListFragment 时,这仅在第一次屏幕旋转之前有效。旋转屏幕后,我可以在调试器中看到 Android 恢复了旧的 ListFragment 并创建了一个新的,原因是

CustomListFragment fragment = new CustomListFragment();
fragmentTransaction.add(R.id.customFragmentContainer, fragment);

创建一个新的 ListFragment 的地方。当我长按一个项目打开 ContextMenu 时,onCreateContextMenu会调用新 ListFragment 的方法,并将结果传递给onContextItemSelected旧 ListFragment 的方法。

我认为当我发布一些代码时它会变得更清楚:

这是我的 ListFragment:

public class CustomListFragment extends ListFragment {

private LayoutInflater layoutInflater;
private OnSelectedListener<String> selectionListener;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    layoutInflater = inflater;
    return inflater.inflate(R.layout.list_fragment_layout, null);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setListAdapter(new CustomListAdapter());
    registerForContextMenu(getListView());
}

public void setOnSelectedListener(OnSelectedListener<String> listener) {
    selectionListener = listener;
}

private static final String item0 = "item0";
private static final String item1 = "item1";

@Override
public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    menu.add(0, 0, 0, item0);
    menu.add(0, 1, 0, item1);
}
@Override
public boolean onContextItemSelected(MenuItem menuItem) {
    String selection;
    if (menuItem.getItemId()==0)
        selection = item0;
    else
        selection = item1;

    if (selectionListener!=null)
        selectionListener.onSelected(selection);
    return true;
}

private class CustomListAdapter extends BaseAdapter  {

    private List<String> elemente = new ArrayList<String>();

    public CustomListAdapter() {
        elemente.add("one");
        elemente.add("two");
        elemente.add("three");
    }

    @Override
    public int getCount() {
        return elemente.size();
    }

    @Override
    public Object getItem(int position) {
        return elemente.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView==null)
            convertView = layoutInflater.inflate(R.layout.element, null);
        TextView tv = (TextView)convertView;
        tv.setText(elemente.get(position));
        return tv;
    }
}
}

有了这个 Activity 它工作正常:

public class CustomFragmentActivity extends FragmentActivity implements OnSelectedListener<String> {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.fragment_layout);

    FragmentManager fragmentManager = getSupportFragmentManager();
    CustomListFragment fragment = (CustomListFragment)fragmentManager.findFragmentById(R.id.customFragment);

    fragment.setOnSelectedListener(this);
}

@Override
public void onSelected(String selection) {
    Toast.makeText(this, selection, Toast.LENGTH_LONG).show();
}
}

但是有了这个 Activity 它只在第一次屏幕旋转之前有效:

    public class CustomFragmentContainerActivity extends FragmentActivity implements OnSelectedListener<String> {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.fragment_container_layout);

    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    CustomListFragment fragment = new CustomListFragment();
    fragmentTransaction.add(R.id.customFragmentContainer, fragment);
    fragmentTransaction.commit();

    fragment.setOnSelectedListener(this);
}

@Override
public void onSelected(String selection) {
    Toast.makeText(this, selection, Toast.LENGTH_LONG).show();
}
}

OnSelectedListener 只是一个提供一个公共方法的接口。屏幕旋转后,结果(所选项目)被传递给旧的 ListFragment。但是这个旧的 ListFragment 是由 Android 系统重新创建的,并且 selectionListener 为 null,所以什么也没有发生。界面如下所示:

public interface OnSelectedListener<V> {
    public void onSelected(V selection);
}

最后,也许我应该提到我正在使用 v4 支持库。

4

1 回答 1

0

好的,问题是,支持库中存在内存泄漏,并且旧片段的 onContextItemSelected() 方法被调用。当我返回 true 时,较新的片段不会得到这个方法调用。

于 2012-08-30T16:50:28.460 回答