我最近了解到how to make nested fragments in Android .不过,我不知道应该如何进行交流。
从阅读 fragment communication documentation我知道
All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.
这对于 Activity 中的兄弟 Fragment 是有意义的,但对于父子 Fragment 通信而言意义不大。我是否需要一直到 Activity 才能让子 fragment 与父 fragment 交谈?如果答案是简单的"is",那么我可以做到。如果是“否”,那么代码设计会是什么样子?
我在 Nested Fragment documentation 中看到可以使用getParentFragment()
获取对父 fragment 的引用。那么这是否意味着 child 应该直接与 parent 沟通呢?这似乎与正常 fragment 与父 Activity 通信所鼓励的相反。
最佳答案
按照 Rahul Sharma 在评论中的建议,我使用接口(interface)回调从子 fragment 到父 fragment 和 Activity 进行通信。我也是submitted this answer to Code Review .我认为那里没有答案(在撰写本文时)表明这种设计模式没有重大问题。在我看来,这与官方 fragment communication docs 中给出的一般指导一致。 .
示例项目
以下示例项目扩展了问题中给出的示例。它具有启动从 Fragment 到 Activity 以及从 Child Fragment 到 Parent Fragment 的向上通信的按钮。
我这样设置项目布局:
主要 Activity
Activity 实现了两个 fragment 的监听器,以便可以从它们获取消息。
可选 TODO:如果 Activity 想要启动与 Fragment 的通信,它可以直接获取对它们的引用,然后调用它们的公共(public)方法之一。
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity implements ParentFragment.OnFragmentInteractionListener, ChildFragment.OnChildFragmentToActivityInteractionListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.parent_fragment_container, new ParentFragment());
ft.commit();
}
@Override
public void messageFromParentFragmentToActivity(String myString) {
Log.i("TAG", myString);
}
@Override
public void messageFromChildFragmentToActivity(String myString) {
Log.i("TAG", myString);
}
}
父 fragment
Parent Fragment 从 Child Fragment 实现监听器,以便它可以接收来自它的消息。
可选 TODO:如果父 Fragment 想要启动与子 Fragment 的通信,它可以直接获取对它的引用,然后调用其公共(public)方法之一。
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ParentFragment extends Fragment implements View.OnClickListener, ChildFragment.OnChildFragmentInteractionListener {
// **************** start interesting part ************************
private OnFragmentInteractionListener mListener;
@Override
public void onClick(View v) {
mListener.messageFromParentFragmentToActivity("I am the parent fragment.");
}
@Override
public void messageFromChildToParent(String myString) {
Log.i("TAG", myString);
}
public interface OnFragmentInteractionListener {
void messageFromParentFragmentToActivity(String myString);
}
// **************** end interesting part ************************
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_parent, container, false);
view.findViewById(R.id.parent_fragment_button).setOnClickListener(this);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
Fragment childFragment = new ChildFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.replace(R.id.child_fragment_container, childFragment).commit();
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
}
子 fragment
Child Fragment 为 Activity 和 Parent Fragment 定义了监听器接口(interface)。如果 Child Fragment 只需要与其中一个进行通信,则可以删除另一个接口(interface)。
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ChildFragment extends Fragment implements View.OnClickListener {
// **************** start interesting part ************************
private OnChildFragmentToActivityInteractionListener mActivityListener;
private OnChildFragmentInteractionListener mParentListener;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.child_fragment_contact_activity_button:
mActivityListener.messageFromChildFragmentToActivity("Hello, Activity. I am the child fragment.");
break;
case R.id.child_fragment_contact_parent_button:
mParentListener.messageFromChildToParent("Hello, parent. I am your child.");
break;
}
}
public interface OnChildFragmentToActivityInteractionListener {
void messageFromChildFragmentToActivity(String myString);
}
public interface OnChildFragmentInteractionListener {
void messageFromChildToParent(String myString);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
// check if Activity implements listener
if (context instanceof OnChildFragmentToActivityInteractionListener) {
mActivityListener = (OnChildFragmentToActivityInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnChildFragmentToActivityInteractionListener");
}
// check if parent Fragment implements listener
if (getParentFragment() instanceof OnChildFragmentInteractionListener) {
mParentListener = (OnChildFragmentInteractionListener) getParentFragment();
} else {
throw new RuntimeException("The parent fragment must implement OnChildFragmentInteractionListener");
}
}
// **************** end interesting part ************************
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_child, container, false);
view.findViewById(R.id.child_fragment_contact_activity_button).setOnClickListener(this);
view.findViewById(R.id.child_fragment_contact_parent_button).setOnClickListener(this);
return view;
}
@Override
public void onDetach() {
super.onDetach();
mActivityListener = null;
mParentListener = null;
}
}
关于android - Android中嵌套 fragment 之间的通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39491655/