0

その要素に ContextMenu を提供する ListFragment があります。このフラグメントを xml-layout に配置するとすべて正常に動作しますが、この ListFragment を FragmentManager を介してプログラムで追加すると、これは最初の画面回転までしか機能しません。画面を回転させた後、Android が古い ListFragment を復元し、新しい 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;
    }
}
}

このアクティビティを使用すると、正常に動作します。

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();
}
}

ただし、このアクティビティでは、最初の画面回転までしか機能しません。

    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 に答える