複数のActivity
を持つFragment
があります。 DialogFragment
を表示するか、Fragment
sの1つから別のFragment
を開きたい。 Activity
はFragment
sを開くタスクである必要があることを知っているので、代わりにいくつかのことを試しました。
[〜#〜]最初の[〜#〜]getActivity()
を使用してキャストしようとしたので、Activity
のメソッドを呼び出してFragment
を表示できますが、これによりFragment
とActivity
の依存関係が作成されるため、追加を避けたいと思います。可能であれば依存関係。
[〜#〜]秒[〜#〜]
次に、リスナーがActivity
にFragment
を表示する必要があることを通知しようとしました。そこで、リスナーインターフェイスを実装するためにActivity
にクラスを作成しました。しかし、New MyActivity().new Listener();
を使用する必要があり、getSupportFragmentManager()
を使用しようとすると、Exception
のこのインスタンスが初期化されていないため、Activity
がスローされるため、問題が発生しました。
[〜#〜]サード[〜#〜]
次に、Activity
にリスナーを直接実装させようとしました。これは、アクティビティではなく、リスナーとの依存関係のみを作成しているためです。しかし今、私はActivity
が2〜4の異なるインターフェースを実装するようになり、まとまりが大幅に低下するため、躊躇しています。
ですから、私が試した方法は、レンガの壁にぶつかり、依存関係を作成しているようです。作成する必要があるかどうかはわかりません。私は失敗し、これらのオプションの1つを使用する必要がありますか?もしそうなら、どのオプションが最適でしょうか?どんな助けや提案も大歓迎です。
個人的には、フラグメントは再利用可能でモジュール式のコンポーネントと見なす必要があると思います。したがって、この再利用性を提供するために、フラグメントは親アクティビティについてあまり知らないはずです。しかし、その見返りとして、活動は彼らが保持している断片について知らなければなりません。
したがって、最初のオプションは、非常に高度に結合されたコードを引き起こすと述べた依存関係の理由から、私の意見では決して考慮されるべきではありません。
2番目のオプションについては、フラグメントは、アプリケーションフローまたはUI関連の決定(新しいフラグメントの表示、フラグメント固有のイベントがトリガーされたときの処理の決定など)を親アクティビティに委任できます。したがって、リスナー/コールバックはフラグメント固有である必要があり、したがってフラグメントで宣言する必要があります。そして、これらのフラグメントを保持するアクティビティは、これらのインターフェイスを実装し、何をするかを決定する必要があります。
したがって、私にとっては3番目のオプションの方が理にかなっています。アクティビティは、特定のコールバックで保持および実行していることに関して、より読みやすいと思います。しかし、そうです、あなたの活動は神の対象になるかもしれません。
複数のインターフェースを実装したくない場合は、Squareの Otto プロジェクトを確認できます。基本的にはイベントバスです。
インターフェースを作成する
public interface ListenFromActivity {
void doSomethingInFragment();
}
アクティビティクラスListenFromActivity
インターフェイスの参照を保持します
public ListenFromActivity activityListener;
リスナーを設定するパブリックメソッドを作成する
public void setActivityListener(ListenFromActivity activityListener) {
this.activityListener = activityListener;
}
アクティビティクラスにトリガーポイントを追加します。ここではユーザーインタラクションを使用しました
@Override
public void onUserInteraction() {
super.onUserInteraction();
if (null != activityListener) {
activityListener.doSomethingInFragment();
}
}
今フラグメントクラス
フラグメントにインターフェースクラスを実装させる
public class SomeFragment extends Fragment implements ListenFromActivity
Android Studioは、インターフェースのメソッドをフラグメントで実装するように促します
void doSomethingInFragment()
{//Add your code here
}
フラグメントonCreate
メソッドでこのようなアクティビティを実行する最後のパーツパーツリスナーインスタンス
((ListnerActivity) getActivity()).setActivityListener(SomeFragment.this);
完了!!。これで、アクティビティからフラグメントメソッドを呼び出すことができます。
FragmentXからFragmentActivityにデータを渡す必要があります。FragmentActivityはこのデータをFragmentYに渡します。これは、フラグメントクラスで定義されたインターフェイスを介して行い、onAttach()で定義されたコールバックをインスタンス化します。
これを行う方法の詳細はこちら 他のフラグメントとの通信
簡単な例として、フラグメントAとフラグメントBについて考えてみます。フラグメントAはリストフラグメントであり、アイテムを選択すると、フラグメントBに表示される内容が変わります。簡単ですね。
最初に、フラグメントAをそのように定義します。
public class FragmentA extends ListFragment{
//onCreateView blah blah blah
}
そしてここにフラグメントBがあります
public class FragmentB extends Fragment{
//onCreateView blah blah blah
}
そして、これが両方を管理する私のFragmentActivityです
public class MainActivity extends FragmentActivity{
//onCreate
//set up your fragments
}
おそらくあなたはすでにこのようなものを持っているでしょう、今ここにあなたがFragmentA(私たちがいくつかのデータを取得するために必要なリストフラグメント)を変更する方法があります。
public class FragmentA extends ListFragment implements onListItemSelectedListener, onItemClickListener{
OnListItemSelectedListener mListener;
//onCreateView blah blah blah
// Container Activity must implement this interface
public interface OnListItemSelectedListener {
public void onListItemSelected(int position);
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mListener = (OnListItemSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnListItemSelectedListener");
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
//Here's where you would get the position of the item selected in the list, and pass that position(and whatever other data you need to) up to the activity
//by way of the interface you defined in onAttach
mListener.onListItemSelected(position);
}
ここで最も重要な考慮事項は、親アクティビティがこのインターフェイスを実装することです。そうしないと、例外が発生します。正常に実装された場合、リストフラグメント内のアイテムが選択されるたびに、アクティビティにその位置が通知されます。明らかに、任意の数またはタイプのパラメーターを使用してインターフェースを変更できます。この例では、整数位置を渡すだけです。これが少しの人、幸運を明らかにすることを願っています。
2番目の選択肢は正しい方向に進んでいると思います。
フラグメントで、リスナーインターフェイスを定義します。
class MyFragment ...
{
public interface IMyFragmentListenerInterface
{
void DoSomething();
}
}
アクティビティにインターフェースを実装させます。
class MyActivity
{
class MyListener1 implements IMyFragmentListenerInterface { ... }
}
リスナーをフラグメントに渡します。私はフラグメントのコンストラクターでそれを行うのが好きですが、それはフラグメントを完全に自分で管理する場合にのみ機能します。代わりに、フラグメントにsetListener
メソッドを追加できます。
ただ ドキュメントに従ってください :
Fragment
:
public class HeadlinesFragment extends Fragment {
// Container Activity must implement this interface
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
OnHeadlineSelectedListener mCallback;
// "Bind" to the Activity where this Fragment lives
public void setOnHeadlineSelectedListener(Activity activity) {
mCallback = (OnHeadlineSelectedListener) activity;
}
// ...
// This will send info to the Activity where the Fragment lives
private void someOtherFunctionOrListener(int position) {
mCallback.onArticleSelected(position); // pass info into Activity
}
}
Activity
:
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
// ...
@Override
public void onAttachFragment(Fragment fragment) {
if (fragment instanceof HeadlinesFragment) {
HeadlinesFragment headlinesFragment = (HeadlinesFragment) fragment;
headlinesFragment.setOnHeadlineSelectedListener(this);
}
}
@Override
public void onArticleSelected(int position) {
// Call received from Fragment
}
}
このようなものを試しましたか(フラグメントから):
FragmentTransaction ft =
getActivity().getSupportFragmentManager().beginTransaction();
Fragment prev =
getActivity().getSupportFragmentManager().findFragmentByTag("some_name");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
DialogFragment dialogFragment = DialogFragmentClass.newInstance();
dialogFragment.show(ft, "some_name");
教えてください、乾杯。
疎結合を最大限に活用するには、SquareのOTTOやGreenRobotのEventBusなどのイベントバスを使用できます。フラグメントは、アクティビティによって処理されるイベントを発生させる可能性があり、その逆も同様です。これのすばらしい点は、コンポーネント(アクティビティ、フラグメント)が相互に何も関係がなく、インターフェイスやコールバックを宣言する必要がないことです。
私はすべてのプロジェクトで使用していますが、堅牢で、パフォーマンスへの影響はほとんどまたはまったくありません(通常の状態)。