在Android中重用片段

时间:2014-02-08 07:32:53

标签: android android-intent android-fragments android-activity

我有一个包含TextViewEditTextButton的片段。我还有2个活动,包括其中一个活动的按钮fragmentonClick,另一个活动开始。通过intenttext中的edittext成为另一个text textview的{​​{1}}。

我有两个可供选择的设计决定

  1. 使用构造适当意图的适当方法创建两个此类片段类。从相应的片段对象内部访问UI元素并开始活动。
  2. 只创建一个片段类。 onClick,将事件传递给活动中的特定方法(活动都有此方法),活动具有构建意图和启动其他活动的逻辑
  3. 考虑如果有100个此类活动会发生什么。第一种方法是让我们用自定义方法编写100个不同的片段类,但在第二种方法中,它是一个单独的类,并且活动在特别命名的方法中具有自定义逻辑。

    因此我选择了第二种选择并且我意识到UI元素无法在activity活动方法中实例化,因为片段的布局尚未膨胀。我正在onCreate中进行实例化作为解决方法。

    这是不好的做法,还是有更好的onStart可供使用?

2 个答案:

答案 0 :(得分:1)

建议的模式是创建一个holder接口,任何想要实例化你的片段的活动都必须实现。另外,要为新片段中的视图设置数据,请在片段上创建newInstance()工厂方法。

我倾向于像这样接近它;

class FooFragment implements Fragment {

    private static final String TEXT_FOR_TEXTVIEW = "textForTextView";

    private FooFragmentHolder mHolder;

    /*
     * Rather than creating your fragment in your layout directly
     * you should instead instantiate it using this class in your 
     * activity.
     */
    public static FooFragment newInstance(String text) {
         Bundle data = new Bundle();
         data.putString(TEXT_FOR_TEXTVIEW, text);
         FooFragment fooFragment = new FooFragment();
         fooFragment.setArguments(data);
         return fooFragment;
    }

    public interface FooFragmentHolder {
         public void buttonPressed(String editTextContent);
    }

    /*
     * When we create the fragment with the activity we use onAttach to get
     * our holder implementation (the activity)
     */
    @Override
    public void onAttach(Activity activity) {
         if (activity instanceof FooFragmentHolder) {
             mHolder = (FooFragmentHolder) activity;
         } else {
             throw new IllegalStateException("Containing activity must implement FooFragmentHolder");
         }
    }

    @Override
    public void onCreateView(Inflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_foo, container, false);

        final EditText editText = (EditText) view.findViewById(R.id.edit_text);
        Button button = (Button) view.findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(Button button) {
                mHolder.buttonPressed(editText.getText());
            }

        })};
        TextView textView = (TextView) view.findViewById(R.id.text_view);

        Bundle args = getArguments();
        if (args != null) {
            textView.setText(args.getString(TEXT_FOR_TEXTVIEW));
        }

        return view;
    }

}

现在,在您的活动中,您只需要实现FooFragmentHolder接口并使用我们创建的newInstance方法;

class FooActivity extends Activity implements FooFragment.FooFragmentHolder {

    private static final String TEXT_FOR_TEXTVIEW = "textForTextView";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentLayout(R.layout.activity_foo);

        // Instead of creating your fragment in your layout, create a holder
        // layout and attach a new instance of your fragment using a fragment
        // transaction.
        FooFragment fooFragment = FooFragment.newInstance(getIntent().getStringExtra(TEXT_FOR_TEXTVIEW));
        getFragmentManager().beginTransaction()
            .replace(R.id.content, fooFragment)
            .commit();
    }

    @Override
    public void buttonPressed(String editTextContent) {
        // In this case just starting the next FooActivity, but logic could be
        // applied for any other activity.
        Intent intent = new Intent(this, FooActivity.class)
            .putExtra(TEXT_FOR_TEXTVIEW, editTextContent);
        startActivity(intent);
    }

}

答案 1 :(得分:0)

我决定以下面的模式解决 -

包含此片段的任何活动都应实现类似

的接口
public interface ViewsCreatedListener {
    public void onViewsCreated();
}

该活动看起来像

public class ExampleActivity extends Activity implements ViewsCreatedListener {
     .
     .
     .
     .
     @Override
     public void onViewsCreated() {
          //Initiate the views here and do what gotta be done
     }
}

该片段应检查包含此片段的任何活动是否应使用onAttach方法和onActivityCreated实现该接口,并通知活动

public class ExampleFragment extends Fragment {

     ViewsCreatedListener listener = null;
     .
     .
     .
     .
     @Override
     public onAttach(Activity activity) {
         super.onAttach(activity);
         try {
           listener = (ViewsCreatedListener) activity;
         } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement ViewsCreatedListener");
     }

     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         listener.onViewsCreated();
     }

}

这样做,片段只提供UI,包含活动决定应该通过片段包含的UI元素做什么。这最大化了可重用性.. DRY ...... :-D