Joakim Ericsson
Joakim Ericsson

Reputation: 4696

Call an activity method from a fragment

Trying to call a method in my activity from a fragment. I want the fragment to give the method data and to get the data when the method return. I want to achieve similar to call on a static method, but without the use of static because it create problems in the activity.

New to fragments so I need an easy and pedagogic explanation!

Thanks!

Upvotes: 387

Views: 372811

Answers (18)

Ronnie
Ronnie

Reputation: 255

I think it would be a better approach to pass the activity instance on fragment initialization. I passed the instance like below:

class FragmentSignUp : Fragment() {

    private lateinit var authActivity: AuthenticateActivity

    ...
    
    companion object {

        fun newInstance(a: AuthenticateActivity): FragmentSignUp {
            val fragment = FragmentSignUp()
            fragment.authActivity = a
            return fragment
        }
    }
}

Now you can initialize the fragment with the activity instance passed on and also can call any public method in your activity. Like below:

val fragmentManager = supportFragmentManager
val fragment = FragmentSignUp.newInstance(this)

fragmentManager.beginTransaction().replace(R.id.authenticate_fragment, fragment, FragmentSignUp::class.java.simpleName)
            .commit()

You can now access your activity public method in your fragment; like in my case:

authactivity.goToLogInFragment()

In Java your fragment class should be:

public class FragmentSignUp extends Fragment {

    private AuthenticateActivity authActivity;

    public static FragmentSignUp newInstance(AuthenticateActivity a) {
        FragmentSignUp fragment = new FragmentSignUp();
        fragment.authActivity = a;
        return fragment;
    }
}

Note: We can also inject the activity directly into the fragment constructor. But in most cases we should avoid that since it can cause some runtime issues.

Upvotes: -1

Abhay
Abhay

Reputation: 647

Best way to call the activity method from their respective fragment

(activity as YourActivity).activtiyMethod()

use this line from your activity. For example

Suppose You have Activity A and method add() and your fragment ABC and you want to call the method add from Fragment ABC,

(activity as A).add()

Upvotes: 7

Vivek Beladiya
Vivek Beladiya

Reputation: 1

From fragment to activity:

((YourActivityClassName)requireActivity()).yourPublicMethod();

Upvotes: 0

Droid Chris
Droid Chris

Reputation: 3783

Here is how I did this:

first make interface

interface NavigationInterface {
    fun closeActivity()
}

next make sure activity implements interface and overrides interface method(s)

class NotesActivity : AppCompatActivity(), NavigationInterface {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_notes)
        setSupportActionBar(findViewById(R.id.toolbar))
    }

    override fun closeActivity() {
        this.finish()
    }
}

then make sure to create interface listener in fragment

private lateinit var navigationInterface: NavigationInterface

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
): View? {
    //establish interface communication
    activity?.let {
        instantiateNavigationInterface(it)
    }
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_notes_info, container, false)
}

private fun instantiateNavigationInterface(context: FragmentActivity) {
    navigationInterface = context as NavigationInterface
}

then you can make calls like such:

view.findViewById<Button>(R.id.button_second).setOnClickListener {
    navigationInterface.closeActivity()
}

Upvotes: 9

Lucy
Lucy

Reputation: 436

Thanks @BIJAY_JHA and @Manaus. I used the Kotlin version to call my signIn() method that lives in the Activity and that I'm calling from a Fragment. I'm using Navigation Architecture in Android so the Listener interface pattern isn't in the Fragment:

 (activity as MainActivity).signIn() 

Upvotes: 4

Infomaster
Infomaster

Reputation: 871

For Kotlin try it out

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

Upvotes: 1

BIJAY_JHA
BIJAY_JHA

Reputation: 31

((your_activity) getActivity).method_name()

Where your_activity is the name of your activity and method_name() is the name of the method you want to call.

Upvotes: 2

Sergio Vel&#225;squez
Sergio Vel&#225;squez

Reputation: 71

I have tried with all the methods shown in this thread and none worked for me, try this one. It worked for me.

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

Upvotes: 1

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

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

Note : class name should be in public

Upvotes: 0

Maravilho Singa
Maravilho Singa

Reputation: 224

I have been looking for the best way to do that since not every method we want to call is located in Fragment with same Activity Parent.

In your Fragment

public void methodExemple(View view){

        // your code here

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

In your Activity

new ExempleFragment().methodExemple(context); 

Upvotes: 1

Maya Mohite
Maya Mohite

Reputation: 683

In kotlin you can call activity method from fragment like below:

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

Upvotes: 6

Wasim K. Memon
Wasim K. Memon

Reputation: 6067

For Kotlin developers

(activity as YourActivityClassName).methodName()

For Java developers

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

Upvotes: 102

hispeed
hispeed

Reputation: 171

For accessing a function declared in your Activity via your fragment please use an interface, as shown in the answer by marco.

For accessing a function declared in your Fragment via your activity you can use this if you don't have a tag or an 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


}

This is the 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);
    }
}

This answer is for noobs like me. Have a good day.

Upvotes: 3

Mathan Chinna
Mathan Chinna

Reputation: 597

This is From Fragment class...

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

This Code From Activity Class...

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

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

Upvotes: 2

A.Alqadomi
A.Alqadomi

Reputation: 1589

Although i completely like Marco's Answer i think it is fair to point out that you can also use a publish/subscribe based framework to achieve the same result for example if you go with the event bus you can do the following

fragment :

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

Activity:

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

}

Upvotes: 10

sivi
sivi

Reputation: 11144

Update after I understand more how fragments work. Each fragment belongs to a parent activity. So just use:

getActivity().whatever

From within the fragment. It is a better answer because you avoid superflous casts. If you cannot avoid the casts with this solution use the one below.

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

what you have to do is to cast to the outer activity

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

creating a new instance will be confusing the android frame and it will not be able to recognize it. see also :

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

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

Upvotes: 17

Marco RS
Marco RS

Reputation: 8255

You should probably try to decouple the fragment from the activity in case you want to use it somewhere else. You can do this by creating a interface that your activity implements.

So you would define an interface like the following:

Suppose for example you wanted to give the activity a String and have it return a Integer:

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

This can be defined in the fragment or a separate file.

Then you would have your activity implement the interface.

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

}

Then in your fragment you would have a MyStringListener variable and you would set the listener in fragment onAttach(Activity activity) method.

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

    }

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

The first answer definitely works but it couples your current fragment with the host activity. Its good practice to keep the fragment decoupled from the host activity in case you want to use it in another acitivity.

Upvotes: 234

Richard
Richard

Reputation: 14635

From fragment to activty:

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

From activity to fragment:

FragmentManager fm = getSupportFragmentManager();

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

If you added fragment via code and used a tag string when you added your fragment, use findFragmentByTag instead:

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

Upvotes: 946

Related Questions