フラグメントからアクティビティメソッドを呼び出す


318

フラグメントから私のアクティビティのメソッドを呼び出そうとしています。フラグメントがメソッドデータを提供し、メソッドが戻るときにデータを取得する必要があります。静的メソッドの呼び出しと同様に達成したいのですが、アクティビティで問題が発生するため、静的メソッドを使用しません。

フラグメントが初めてなので、簡単で教育的な説明が必要です。

ありがとう!

回答:


820

フラグメントからアクティビティへ:

((YourActivityClassName)getActivity()).yourPublicMethod();

アクティビティからフラグメントへ:

FragmentManager fm = getSupportFragmentManager();

//if you added fragment via layout xml
YourFragmentClass fragment = (YourFragmentClass)fm.findFragmentById(R.id.your_fragment_id);
fragment.yourPublicMethod();

コードを使用しtagてフラグメントを追加し、フラグメントを追加するときに文字列を使用した場合は、findFragmentByTag代わりに次を使用します。

YourFragmentClass fragment = (YourFragmentClass)fm.findFragmentByTag("yourTag");

5
キャストが機能しない場合、予期しない事態が発生するので注意してください。:S
Ewoks

48
キャストの問題を回避するには、以下を使用します。Activity act = getActivity(); if(act instanceof YourActivityClassName)((YourActivityClassName)act).yourPublicMethod(); }
ericharlow 2013

@Richard:アクティビティ内でフラグメントのメソッドを実行する必要がある場合など、反対のアクションをどのように実行できますか?
Himanshu 2013年

5
アクティビティをキャストするのは悪い設計であり、安全ではありません。フラグメントは特定のアクティビティに限定されません。
アビブベンシャバット2015年

3
@ケイ必ずしもそうではありません。フラグメントは、分解されたより大きなアクティビティの「フラグメント」として使用できます。たとえば、レスポンシブUIを作成します。私はめったに同じフラグメントを使用せず、それを異なるアクティビティホストにアタッチします。
Richard

201

別の場所で使用する場合は、フラグメントをアクティビティから分離することをお勧めします。これを行うには、アクティビティが実装するインターフェースを作成します。

したがって、次のようなインターフェースを定義します。

たとえば、アクティビティに文字列を指定して、整数を返すようにしたいとします。

public interface MyStringListener{
    public Integer computeSomething(String myString);
}

これは、フラグメントまたは個別のファイルで定義できます。

次に、アクティビティにインターフェースを実装させます。

public class MyActivity extends FragmentActivity implements MyStringListener{

  @Override
  public Integer computeSomething(String myString){
   /** Do something with the string and return your Integer instead of 0 **/ 
   return 0;
  }

}

次に、フラグメントにMyStringListener変数を設定し、リスナーをフラグメントのonAttach(Activityアクティビティ)メソッドに設定します。

public class MyFragment {

        private MyStringListener listener;

        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            try {
                listener = (MyStringListener) context;
            } catch (ClassCastException castException) {
                /** The activity does not implement the listener. */
            }
        }

    }

編集(17.12.2015):onAttach(Activity activity) is deprecated, use onAttach(Context context) instead, it works as intended

最初の答えは間違いなく機能しますが、現在のフラグメントをホストアクティビティと結び付けます。別のアクティビティで使用する場合に備えて、フラグメントをホストアクティビティから切り離しておくことをお勧めします。


58
これを検討している他の人にとっては、受け入れられた答えは明らかに機能しますが、これは設計の観点からはより優れた安全なアプローチです。
ポールリヒター

7
この答えは、コード設計の点ではるかに優れています。また、アクティビティが誤ってキャストされてもクラッシュは発生しません
David T.

3
+1が、onAttachでtry-catchを使用しません。失敗させましょう。リスナーがオプションの場合(つまり、失敗することが適切でない場合)、フラグメントにset / addListenerメソッドを追加します。
ataulm 2014

反対側のコミュニケーションについては、developer.android.com/ training/basics/fragments/…をご覧ください。フラグメントのインターフェースを使用して(これは、前述のフラグメント->アクティビティ通信を行うための安全な方法でもあります)、フラグメント->アクティビティに基づいてアクションを実行したい場合は、アクティビティからフラグメント内にあるメソッドを呼び出すこともできます。通信。
ケレム2014年

フラグメントは再利用され、任意のアクティビティで設定されることを意図しています。同じフラグメントを使用する5つのアクティビティがある場合はどうなりますか?マルコの答えは正しいものであり、フラグメント間およびアクティビティとフラグメントのコミュニケーションのための良い習慣です
blockwala

51

Kotlinの開発者

(activity as YourActivityClassName).methodName()

のJava開発者

((YourActivityClassName) getActivity()).methodName();

このコードを実行すると、kotlinでエラーが発生します。別の方法はありますか?
Jake Garbo、

1
実行すると。私はActivityClassのnull値を取得します、これはkotlinでこれを行うのにエラーがなくても適切な方法ではないと思います。それともバグ?
Jake Garbo、

@JakeGarboその適切な方法でなければ、12人が投票していません。2つ目は、getActivity()がnullを返すことです。SOでこれらの質問を確認してください。
Wasim K. Memon

@JakeGarbo Ya彼らはあなたに言った。それがうまくいった場合は、感謝するか、他の方法を見つけるか、最初にコーディング方法を学びます。
Wasim K. Memon

13

フラグメントがどのように機能するかを理解した後で更新します。各フラグメントは親アクティビティに属しています。だからちょうど使用:

getActivity().whatever

フラグメント内から。余計なキャストを避けるため、これはより良い答えです。この解決策でキャストを回避できない場合は、以下の解決策を使用してください。

============

あなたがしなければならないことは、外側のアクティビティにキャストすることです

((MainActivity) getActivity()).Method();

新しいインスタンスを作成すると、Androidフレームが混乱し、認識できなくなります。また見なさい:

https://stackoverflow.com/a/12014834/1984636

https://stackoverflow.com/a/2042829/1984636


9

私は完全にマルコの答えが好きですが、パブリッシュ/サブスクライブベースのフレームワークを使用して同じ結果を達成できることを指摘するのは公平だと思います。たとえば、イベントバスを使用すると、次のことができます。

フラグメント:

EventBus.getDefault().post(new DoSomeActionEvent()); 

アクティビティ:

 @Subscribe
onSomeActionEventRecieved(DoSomeActionEvent doSomeActionEvent){
//Do something

}

5

kotlinでは、以下のようにフラグメントからアクティビティメソッドを呼び出すことができます。

var mainActivity: MainActivity = activity as MainActivity
        mainActivity.showToast() //Calling show toast method of activity

2

フラグメントを介してアクティビティで宣言された関数にアクセスするには、marcoの回答に示されているインターフェースを使用してください。

アクティビティを介してフラグメントで宣言された関数にアクセスするには、タグまたはIDがない場合にこれを使用できます

private void setupViewPager(ViewPager viewPager) {
    //fragmentOne,fragmentTwo and fragmentThree are all global variables
    fragmentOne= new FragmentOne();
    fragmentTwo= new FragmentTwo();
    fragmentThree = new FragmentThree();

    viewPagerAdapteradapter = new ViewPagerAdapter(getSupportFragmentManager());
    viewPagerAdapteradapter.addFragment(fragmentOne, "Frag1");
    viewPagerAdapteradapter.addFragment(fragmentTwo, "Frag2");
    viewPagerAdapteradapter.addFragment(fragmentThree, "Frag3");

    //viewPager has to be instantiated when you create the activity:
    //ViewPager viewPager = (ViewPager)findViewById(R.id.pager);
    //setupViewPager(viewPager);
    //Where R.id.pager is the id of the viewPager defined in your activity's xml page.

    viewPager.setAdapter(viewPagerAdapteradapter);


    //frag1 and frag2 are also global variables
    frag1 = (FragmentOne)viewPagerAdapteradapter.mFragmentList.get(0);
    frag2 = (FragmentTwo)viewPagerAdapteradapter.mFragmentList.get(1);;


    //You can use the variable fragmentOne or frag1 to access functions declared in FragmentOne


}

これはViewpagerAdapterClassです

    class ViewPagerAdapter extends FragmentPagerAdapter {
    public final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

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

    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }
}

この答えは私のような初心者向けです。良い一日を過ごしてください。


1

これはFrom Fragmentクラスです...

((KidsStoryDashboard)getActivity()).values(title_txt,bannerImgUrl);

アクティビティクラスからのこのコード...

 public void values(String title_txts, String bannerImgUrl) {
    if (!title_txts.isEmpty()) {

//Do something to set text 
    }
    imageLoader.displayImage(bannerImgUrl, htab_header_image, doption);
}

1

私はこのスレッドに示されているすべてのメソッドを試しましたが、どれもうまくいきませんでした。これを試してください。それは私のために働いた。

((MainActivity) getContext().getApplicationContext()).Method();

0

呼び出すすべてのメソッドが同じアクティビティの親を持つフラグメントにあるわけではないため、これを行うための最良の方法を探していました。

あなたのフラグメントで

public void methodExemple(View view){

        // your code here

        Toast.makeText(view.getContext(), "Clicked clicked",Toast.LENGTH_LONG).show();
    }

あなたの活動で

new ExempleFragment().methodExemple(context); 


0
((your_activity) getActivity).method_name()

どこにyour_activity自分のアクティビティの名前で、method_name()呼び出したいメソッドの名前です。


0

コトリンのためにそれを試してみてください

class DataForm : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        Tasks(this).getData()
    }

    fun getResponse(response: String) {
        // code
    }
}

class Tasks(private val context: Any) {
    fun getData() {

        val getContext = (context as DataForm).activity
        val getFragment = (context as DataForm)

        val responseListener = Response.Listener<String> { response ->
            getFragment.getResponse(response)
        }

        val errorListener = Response.ErrorListener { error ->
            error.printStackTrace();
        }

        val stringRequest = StringRequest(Request.Method.GET, url, responseListener, errorListener)
        Volley.newRequestQueue(getContext).add(stringRequest)
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.