- public class MainActivity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- MainFragment fragment = new MainFragment();
- fragment.setOnOkBtnClickListener(new MainFragment.OnOkBtnClickListener() {
- @Override
- public void onOkClicked() {
- // TODO Auto-generated method stub
- }
- });
- getFragmentManager().beginTransaction().add(android.R.id.content, fragment, "MainFragment").commit();
- }
- }
- public class MainFragment extends Fragment {
- public interface OnOkBtnClickListener {
- public void onOkClicked();
- }
- private OnOkBtnClickListener mListener;
- public void setOnOkBtnClickListener(OnOkBtnClickListener l) {
- mListener = l;
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- Button okBtn = new Button(inflater.getContext());
- okBtn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if(mListener != null) {
- mListener.onOkClicked();
- }
- }
- });
- return okBtn;
- }
- }
バックグラウンドにある Fragment はメモリが足りなくなると、システムによって破棄され、必要になったときにシステムによって再生成されることがあるため、その際 setOnOkBtnClickListener() 部分は呼ばれないのです。
そのため、システムによって再生成された場合、コールバックを受け取れなくなるということが起こりえます。
以前のエントリで書きましたが、レイアウトで定義した(<fragment> で定義した)Fragment は FragmentTransaction の対象にしてはいけないため、上記のコードの MainFragment が onCreate() 内で生成されるのではなく、レイアウトXMLファイルで定義されている場合は、問題になることは(たぶん)あまりないと思います。
ただ、いずれにしてもこの実装はさけた方が懸命です。 (レイアウトで定義した Fragment を使っているとはいえ、Android UI Cookbook で Activity 側から fragment にリスナーをセットするコードを載せてしまっているので、動的に生成した Fragment には応用しないでください。ごめんなさい。)
で、どうするかというと、Activity 自体にリスナーを実装するようにします。
(私はあまりこの書き方は好きじゃないのですが、Fragment がシステムから再生成されうるのでしょうがないです。。。)
- public class MainActivity2 extends Activity implements MainFragment.OnOkBtnClickListener {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- MainFragment fragment = new MainFragment();
- getFragmentManager().beginTransaction().add(android.R.id.content, fragment, "MainFragment").commit();
- }
- @Override
- public void onOkClicked() {
- // TODO Auto-generated method stub
- }
- }
- public class MainFragment2 extends Fragment {
- public interface OnOkBtnClickListener {
- public void onOkClicked();
- }
- private OnOkBtnClickListener mListener;
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- if (activity instanceof OnOkBtnClickListener == false) {
- throw new ClassCastException("activity が OnOkBtnClickListener を実装していません.");
- }
- mListener = ((OnOkBtnClickListener) activity);
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- Button okBtn = new Button(inflater.getContext());
- okBtn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mListener != null) {
- mListener.onOkClicked();
- }
- }
- });
- return okBtn;
- }
- }
Fragment が Activity の実装に依存しないので、複数の Activity で Fragment を使い回すときに便利です。
Fragment が必ず特定の Activity にしかアタッチされない場合は、次の方法も使えます。
- public class MainActivity3 extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- MainFragment fragment = new MainFragment();
- getFragmentManager().beginTransaction().add(android.R.id.content, fragment, "MainFragment").commit();
- }
- public void onOkClicked() {
- // TODO Auto-generated method stub
- }
- }
- public class MainFragment3 extends Fragment {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- Button okBtn = new Button(inflater.getContext());
- okBtn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- try {
- MainActivity3 activity = (MainActivity3) getActivity();
- activity.onOkClicked();
- } catch (ClassCastException e) {
- throw new ClassCastException("activity が OnOkBtnClickListener を実装していません.");
- }
- }
- });
- return okBtn;
- }
- }
これがベスト!という実装方法がないんですよねー。。。そもそも Fragment のコンストラクタは空コンストラクタでないとダメだよとかって制限があるのに、作れてしまったりするというがフレームワーク的にどうなのよ、と。
しかもシステムに再生成されない限りは普通に動いちゃうので、ぜったいはまるだろこれ、って感じなのです。
0 件のコメント:
コメントを投稿