Panggil metode aktivitas dari sebuah fragmen


318

Mencoba memanggil metode dalam aktivitas saya dari sebuah fragmen. Saya ingin fragmen untuk memberikan data metode dan untuk mendapatkan data ketika metode kembali. Saya ingin mencapai mirip dengan memanggil metode statis, tetapi tanpa menggunakan statis karena itu membuat masalah dalam aktivitas.

Baru mengenal fragmen jadi saya perlu penjelasan yang mudah dan pedagogis!

Terima kasih!

Jawaban:


820

Dari fragmen ke aktivitas:

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

Dari aktivitas hingga fragmen:

FragmentManager fm = getSupportFragmentManager();

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

Jika Anda menambahkan fragmen melalui kode dan menggunakan tagstring ketika Anda menambahkan fragmen Anda, gunakan findFragmentByTagsebaliknya:

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

5
Berhati-hatilah karena hal-hal tak terduga terjadi jika pemeran tidak bekerja ..: S
Ewoks

48
Untuk menghindari masalah pemeran, gunakan: Activity act = getActivity (); if (bertindak instance YourActivityClassName) ((YourActivityClassName) bertindak) .yourPublicMethod (); }
ericharlow

@ Richard: Bagaimana kita bisa melakukan tindakan yang berlawanan, seperti, jika kita harus melakukan metode fragmen di dalam Aktivitas?
Himanshu

5
Desainnya buruk dan tidak aman untuk melakukan suatu Kegiatan. Fragmen tidak terbatas pada Kegiatan tertentu.
Aviv Ben Shabat

3
@ Mungkin tidak perlu. Fragmen dapat digunakan sebagai "fragmen" dari setiap kegiatan yang lebih besar yang dipecah Misalnya untuk membuat UI responsif. Saya jarang menggunakan fragmen yang sama dan melampirkannya pada host aktivitas yang berbeda.
Richard

201

Anda mungkin harus mencoba memisahkan fragmen dari aktivitas jika Anda ingin menggunakannya di tempat lain. Anda dapat melakukan ini dengan membuat antarmuka yang mengimplementasikan aktivitas Anda.

Jadi, Anda akan mendefinisikan antarmuka seperti berikut:

Misalkan misalnya Anda ingin memberikan sebuah String aktivitas dan minta mengembalikan Integer:

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

Ini dapat didefinisikan dalam fragmen atau file terpisah.

Maka Anda akan memiliki aktivitas Anda mengimplementasikan antarmuka.

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

}

Kemudian dalam fragmen Anda, Anda akan memiliki variabel MyStringListener dan Anda akan mengatur pendengar dalam fragmen pada metode Attach (Aktivitas aktivitas).

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. */
            }
        }

    }

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

Jawaban pertama pasti berhasil tetapi pasangan Anda fragmen saat ini dengan aktivitas host. Praktik yang baik untuk menjaga fragmen dipisahkan dari aktivitas host jika Anda ingin menggunakannya dalam kegiatan lain.


58
Bagi siapa pun yang melihat ini, sementara jawaban yang diterima jelas berhasil, ini adalah pendekatan yang lebih baik dan lebih aman dari perspektif desain.
Paul Richter

7
jawaban ini jauh lebih baik dalam hal desain kode. juga tidak akan menyebabkan crash jika aktivitas dicor salah
David T.

3
+1 tapi saya tidak akan menggunakan try-catch di onAttach. Biarkan itu gagal. Jika pendengar adalah opsional (yaitu, gagal tidak sesuai), tambahkan metode set / addListener ke fragmen.
ataulm

Untuk komunikasi pihak lawan, silakan lihat: developer.android.com/training/basics/fragments/… . Menggunakan antarmuka fragmen (yang juga merupakan cara aman untuk melakukan fragmen-> aktivitas comm seperti yang dijelaskan di atas) Anda dapat memanggil metode yang ada di fragmen Anda dari aktivitas Anda juga jika Anda ingin mengambil tindakan berdasarkan fragmen-> aktivitas Anda comm.
Kerem

Fragmen dimaksudkan untuk digunakan kembali dan diatur dalam Kegiatan apa pun. Bagaimana jika saya memiliki 5 aktivitas menggunakan Fragmen yang sama? Jawaban Marco adalah yang benar dan merupakan praktik yang baik untuk komunikasi antar-fragmen dan Activity-Fragment
blockwala

51

Untuk pengembang Kotlin

(activity as YourActivityClassName).methodName()

Untuk pengembang Java

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

itu memberikan kesalahan di kotlin jika kita menjalankan kode ini .. adakah cara lain?
Jake Garbo

1
Ketika saya menjalankannya. Saya mendapatkan nilai nol dari ActivityClass, saya pikir ini bukan cara yang tepat melakukan ini di kotlin bahkan tidak ada kesalahan. atau mungkin bug?
Jake Garbo

@JakeGarbo Cara yang tepat kalau tidak 12 orang belum memilih untuk itu. Hal kedua beberapa kali getActivity () mengembalikan nol memeriksa pertanyaan-pertanyaan itu pada SO.
Wasim K. Memon

@JakeGarbo Ya, mereka memberi tahu Anda. JIKA itu berhasil untuk Anda, maka hargailah atau temukan cara lain atau pelajari cara membuat kode terlebih dahulu.
Wasim K. Memon

13

Perbarui setelah saya lebih memahami cara kerja fragmen. Setiap fragmen milik aktivitas orang tua. Jadi gunakan saja:

getActivity().whatever

Dari dalam fragmen. Ini adalah jawaban yang lebih baik karena Anda menghindari gips superflous. Jika Anda tidak dapat menghindari gips dengan solusi ini gunakan yang di bawah ini.

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

apa yang harus Anda lakukan adalah melakukan aktivitas luar

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

membuat instance baru akan membingungkan bingkai android dan itu tidak akan bisa mengenalinya. Lihat juga :

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

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


9

Meskipun saya benar-benar menyukai Jawaban Marco, saya pikir cukup adil untuk menunjukkan bahwa Anda juga dapat menggunakan kerangka kerja berbasis penerbitan / berlangganan untuk mencapai hasil yang sama, misalnya jika Anda pergi dengan bus acara, Anda dapat melakukan hal berikut

pecahan :

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

Aktivitas:

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

}

5

Di kotlin Anda dapat memanggil metode aktivitas dari fragmen seperti di bawah ini:

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

2

Untuk mengakses fungsi yang dinyatakan dalam Aktivitas Anda melalui fragmen Anda, gunakan antarmuka, seperti yang ditunjukkan dalam jawaban oleh marco.

Untuk mengakses fungsi yang dideklarasikan dalam Fragmen Anda melalui aktivitas Anda, Anda dapat menggunakan ini jika Anda tidak memiliki tag atau 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


}

Ini adalah 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);
    }
}

Jawaban ini untuk pemula seperti saya. Semoga harimu menyenangkan.


1

Ini dari kelas Fragmen ...

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

Kode Ini Dari Kelas Aktivitas ...

 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

Saya telah mencoba dengan semua metode yang ditampilkan di utas ini dan tidak ada yang berhasil untuk saya, coba yang ini. Ini berhasil untuk saya.

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

0

Saya telah mencari cara terbaik untuk melakukan itu karena tidak setiap metode yang ingin kita panggil terletak di Fragmen dengan Induk Kegiatan yang sama.

Dalam Fragmen Anda

public void methodExemple(View view){

        // your code here

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

Dalam Aktivitas Anda

new ExempleFragment().methodExemple(context); 

0

((YourActivityName)getActivity()).functionName();

Contoh: ((SessionActivity)getActivity()).changeFragment();

Catatan: nama kelas harus di tempat umum


0
((your_activity) getActivity).method_name()

Di mana your_activitynama aktivitas Anda dan method_name()nama metode yang ingin Anda panggil.


0

Untuk Kotlin, cobalah

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)
    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.