从片段中调用活动方法


318

尝试从片段中调用活动中的方法。我希望片段提供方法数据并在方法返回时获取数据。我想实现类似于调用静态方法的方法,但是不使用静态方法,因为它会在活动中造成问题。

片段的新手,所以我需要一个简单而教学法的解释!

谢谢!

Answers:


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 2012年

48
为了避免强制转换问题,请使用:Activity act = getActivity(); if(YourActivityClassName的实例)((YourActivityClassName)的行为).yourPublicMethod(); }
ericharlow

@Richard:如果必须在Activity中执行片段的方法,我们如何执行相反的动作?
Himanshu

5
进行Activity的设计很糟糕,也不安全。片段不限于特定活动。
阿维夫·本·沙巴特

3
@Kay不一定。片段可以用作任何较大活动分解的“片段”。例如创建响应式用户界面。我很少使用相同的片段并将其附加到不同的活动主机。
理查德(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 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
对于其他任何人,虽然公认的答案显然是可行的,但从设计角度来看,这是一种更好,更安全的方法。
Paul Richter 2013年

7
这个答案在代码设计方面要好得多。如果活动投放错误,也不会导致崩溃
David T.

3
+1,但我不会在onAttach中使用try-catch。让它失败。如果侦听器是可选的(即失败是不适当的),则将set / addListener方法添加到片段。
ataulm 2014年

有关另一端的信息,请参阅:developer.android.com/training/basics/fragments/…。使用片段的接口(这也是进行fragment-> activity comm的安全方法,如上所述),如果您要基于fragment-> activity进行操作,您也可以从您的活动中调用位于片段中的方法通讯
Kerem 2014年

片段应在任何活动中重用和设置。如果我有5个活动使用相同的片段怎么办?Marco的答案是正确的方法,也是片段间和活动片段通信的良好实践
blockwala 2015年

50

对于Kotlin开发人员

(activity as YourActivityClassName).methodName()

对于Java开发人员

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

如果运行此代码,它将在kotlin中给出错误。还有另一种方法吗?
杰克·嘉宝

1
当我运行它时。我得到ActivityClass的空值,我认为这不是在kotlin中这样做的正确方法,即使没有错误。还是一个错误?
杰克·嘉宝

@JakeGarbo正确的方法,否则12个人没有投票赞成。第二件事是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

尽管我完全喜欢Marco's Answer,但我认为可以指出,您也可以使用基于发布/订阅的框架来达到相同的结果,例如,如果您使用事件总线,则可以执行以下操作

片段:

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

为了通过片段访问您的Activity中声明的函数,请使用接口,如marco的答案所示。

为了通过活动访问在Fragment中声明的函数,可以在没有标签或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

这是来自片段类...

((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

我一直在寻找最好的方法,因为并非我们要调用的每个方法都位于具有相同“活动父级”的Fragment中。

在你的片段

public void methodExemple(View view){

        // your code here

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

在您的活动中

new ExempleFragment().methodExemple(context); 

0

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

范例: ((SessionActivity)getActivity()).changeFragment();

注意:班级名称应公开


0
((your_activity) getActivity).method_name()

your_activity活动的名称在哪里,您method_name()要调用的方法的名称在哪里。


0

对于Kotlin,请尝试一下

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)
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.