从片段中调用活动方法

Joa*_*son 297 android android-fragments

试图从片段中调用我的活动中的方法.我希望片段提供方法数据并在方法返回时获取数据.我希望实现类似于静态方法的调用,但不使用静态因为它在活动中产生问题.

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

谢谢!

Ric*_*ard 768

从片段到激活:

((YourActivityClassName)getActivity()).yourPublicMethod();
Run Code Online (Sandbox Code Playgroud)

从活动到片段:

FragmentManager fm = getSupportFragmentManager();

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

如果您通过代码添加片段并tag在添加片段时使用了字符串,请findFragmentByTag改用:

YourFragmentClass fragment = (YourFragmentClass)fm.findFragmentByTag("yourTag");
Run Code Online (Sandbox Code Playgroud)

  • 要避免使用强制转换问题,请使用:Activity act = getActivity(); if(actofof YourofctivityClassName)((YourActivityClassName)行为).yourPublicMethod(); } (43认同)
  • 如果演员不起作用,请小心导致意外事情发生..:S (5认同)
  • 这是一个糟糕的设计和施放活动不安全.片段不仅限于特定活动. (5认同)
  • @Kay不一定.碎片可以用作分开的任何较大活动的"碎片".例如,创建响应式UI.我很少使用相同的片段并将其附加到不同的活动主机. (3认同)
  • 片段旨在在任何活动中重复使用和设置。如果我有 5 个活动使用同一个 Fragment 怎么办?Marco 的答案是正确的,也是片段间和 Activity-Fragment 通信的好方法。 (2认同)

Mar*_* RS 190

您可能应该尝试将片段与活动分离,以防您想在其他地方使用它.您可以通过创建活动实现的界面来完成此操作.

所以你要定义一个如下界面:

例如,假设您想要为活动赋予一个String并让它返回一个Integer:

public interface MyStringListener{
    public Integer computeSomething(String myString);
}
Run Code Online (Sandbox Code Playgroud)

这可以在片段或单独的文件中定义.

然后你可以让你的活动实现界面.

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

}
Run Code Online (Sandbox Code Playgroud)

然后在你的片段中你将有一个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. */
            }
        }

    }
Run Code Online (Sandbox Code Playgroud)

编辑(2015年12月17日):onAttach(Activity activity) is deprecated, use onAttach(Context context) instead, it works as intended

第一个答案肯定有效,但它将您当前的片段与宿主活动相结合.如果要在另一个活动中使用它,可以将片段与主机活动分离,这是一种很好的做法.

  • 对于其他任何看过这个问题的人来说,虽然接受的答案显然是有效的,但从设计的角度来看,这是更好,更安全的方法. (55认同)
  • 这个答案在代码设计方面要好得多.如果活动输入错误,它也不会导致崩溃 (7认同)
  • +1,但我不会在onAttach中使用try-catch。让它失败。如果侦听器是可选的(即失败是不合适的),则将set / addListener方法添加到片段。 (2认同)

Was*_*mon 38

对于Kotlin开发人员

(activity as YourActivityClassName).methodName()
Run Code Online (Sandbox Code Playgroud)

对于Java开发人员

((YourActivityClassName) getActivity()).methodName();
Run Code Online (Sandbox Code Playgroud)


siv*_*ivi 13

在我更了解片段如何工作之后更新.每个片段都属于父活动.所以只需使用:

getActivity().whatever
Run Code Online (Sandbox Code Playgroud)

从片段内部.这是一个更好的答案,因为你避免了超级演员阵容.如果您无法避免使用此解决方案的演员,请使用下面的演员.

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

你要做的就是投射到外部活动

((MainActivity) getActivity()).Method();
Run Code Online (Sandbox Code Playgroud)

创建一个新实例将混淆Android框架,它将无法识别它.也可以看看 :

/sf/answers/841038411/

/sf/answers/142998061/


A.A*_*omi 9

虽然我完全喜欢Marco的答案,但我认为可以公平地指出你也可以使用基于发布/订阅的框架来实现相同的结果,例如,如果你使用事件总线,你可以执行以下操作

片段:

EventBus.getDefault().post(new DoSomeActionEvent()); 
Run Code Online (Sandbox Code Playgroud)

活动:

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

}
Run Code Online (Sandbox Code Playgroud)


Dro*_*ris 9

我是这样做的:

首先制作界面

interface NavigationInterface {
    fun closeActivity()
}
Run Code Online (Sandbox Code Playgroud)

接下来确保活动实现接口并覆盖接口方法

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()
    }
}
Run Code Online (Sandbox Code Playgroud)

然后确保在片段中创建接口侦听器

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
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样打电话:

view.findViewById<Button>(R.id.button_second).setOnClickListener {
    navigationInterface.closeActivity()
}
Run Code Online (Sandbox Code Playgroud)


Pet*_*ter 7

从各自的片段调用活动方法的最佳方法

(activity as YourActivity).activtiyMethod()
Run Code Online (Sandbox Code Playgroud)

使用您的活动中的这条线。例如

假设您有 Activity A和方法add()以及片段ABC,并且您想从片段 ABC 调用方法 add,

(activity as A).add()
Run Code Online (Sandbox Code Playgroud)


May*_*ite 6

在 kotlin 中,您可以从片段中调用活动方法,如下所示:

var mainActivity: MainActivity = activity as MainActivity
        mainActivity.showToast() //Calling show toast method of activity
Run Code Online (Sandbox Code Playgroud)