从片段调用活动方法

试图从片段中调用我的活动中的方法。我想要片段给方法数据,并在方法返回时获得数据。我想实现类似于对静态方法的调用,但不使用静态,因为它会在活动中产生问题。

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

谢谢!

343825 次浏览

从碎片到活动:

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

如果你通过代码添加fragment,并且在添加fragment时使用了tag字符串,则使用findFragmentByTag代替:

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

您可能应该尝试将片段与活动解耦,以防您想在其他地方使用它。您可以通过创建您的活动实现的接口来做到这一点。

所以你会像下面这样定义一个接口:

例如,假设你想给活动一个String,并让它返回一个Integer:

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

第一个答案肯定有效,但它将当前片段与宿主活动结合在一起。如果你想在另一个活动中使用它,保持片段与宿主活动解耦是很好的做法。

更新后,我了解更多的碎片如何工作。每个片段都属于一个父活动。所以只需使用:

getActivity().whatever

从片段内部。这是一个更好的答案,因为可以避免多余的类型转换。如果这个解决方案不能避免强制转换,请使用下面的方法。

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

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

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

创建一个新的实例将混淆android帧,它将无法识别它。 参见:

https://stackoverflow.com/a/12014834/1984636 < a href = " https://stackoverflow.com/a/12014834/1984636 " > < / >

https://stackoverflow.com/a/2042829/1984636 < a href = " https://stackoverflow.com/a/2042829/1984636 " > < / >

虽然我完全喜欢Marco的回答,但我认为指出你也可以使用基于发布/订阅的框架来实现相同的结果是公平的,例如,如果你使用事件总线,你可以做到以下几点

片段:

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

活动:

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


}

这是来自片段类…

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

这段代码来自Activity类…

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


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

对于通过fragment访问Activity中声明的函数,请使用接口,如marco的回答所示。

如果你没有标签或id,你可以通过活动访问Fragment中声明的函数

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

这个答案是给像我这样的新手的。祝你有愉快的一天。

对于芬兰湾的科特林开发人员

(activity as YourActivityClassName).methodName()

对于Java开发人员

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

在kotlin中,你可以从片段中调用activity方法,如下所示:

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

我一直在寻找最好的方法来做到这一点,因为不是每个方法,我们要调用位于片段与相同的活动父。

在你的碎片里

public void methodExemple(View view){


// your code here


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

在活动中

new ExempleFragment().methodExemple(context);

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

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

注意:类名应该是公开的

我已经尝试了这个线程中显示的所有方法,没有一个对我有效,试试这个。这对我很管用。

((MainActivity) getContext().getApplicationContext()).Method();
((your_activity) getActivity).method_name()

其中your_activity是活动的名称,method_name()是要调用的方法的名称。

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

谢谢@BIJAY_JHA和@Manaus。我使用Kotlin版本来调用我的signIn()方法,该方法存在于活动中,并且我从一个片段中调用。我在Android中使用导航架构,所以监听器接口模式不在片段中:

 (activity as MainActivity).signIn()

以下是我的做法:

首先制作接口

interface NavigationInterface {
fun closeActivity()
}

接下来确保activity实现了接口并覆盖了接口方法

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

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

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
}

然后你就可以这样打电话了:

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

从碎片到活动:

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

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

(activity as YourActivity).activtiyMethod()

使用你活动中的这句话。例如

假设你有活动一个和方法add ()和你的片段美国广播公司,你想从片段ABC调用方法add,

(activity as A).add()

我认为在片段初始化时传递activity实例是更好的方法。我像下面这样传递实例:

class FragmentSignUp : Fragment() {


private lateinit var authActivity: AuthenticateActivity


...
    

companion object {


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

现在,您可以使用传递的活动实例初始化片段,也可以调用活动中的任何公共方法。像下图:

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


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

你现在可以在你的片段中访问你的activity公共方法;就像我的例子:

authactivity.goToLogInFragment()

在Java中,你的片段类应该是:

public class FragmentSignUp extends Fragment {


private AuthenticateActivity authActivity;


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

我们也可以将活动直接注入到片段构造函数中。但在大多数情况下,我们应该避免这样做,因为它会导致一些运行时问题。