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!
This question is related to
android
android-fragments
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.
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()
}
For Kotlin developers
(activity as YourActivityClassName).methodName()
For Java developers
((YourActivityClassName) getActivity()).methodName();
((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);
}
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();
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.
((YourActivityName)getActivity()).functionName();
Example : ((SessionActivity)getActivity()).changeFragment();
Note : class name should be in public
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()
((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.
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);
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
}
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
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)
}
}
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 :
Source: Stackoverflow.com