Làm theo lời khuyên của Rahul Sharma trong các nhận xét, tôi đã sử dụng các cuộc gọi lại giao diện để liên lạc từ Phân đoạn con đến Phân đoạn dành cho phụ huynh và đến Hoạt động. Tôi cũng submitted this answer to Code Review. Tôi lấy câu trả lời không có (tại thời điểm viết bài này) là một dấu hiệu cho thấy không có vấn đề gì lớn với mẫu thiết kế này. Dường như với tôi để phù hợp với hướng dẫn chung được đưa ra trong chính thức fragment communication docs.
Dự án ví dụ
Dự án ví dụ sau mở rộng ví dụ được đưa ra trong câu hỏi. Nó có các nút bắt đầu truyền thông từ các mảnh vỡ đến hoạt động và từ Child Fragment đến Parent Fragment.
tôi thiết lập bố trí dự án như thế này:
Hoạt động chính
Các Hoạt động thực hiện các thính giả của cả hai mảnh để nó có thể nhận được tin nhắn từ họ.
TODO tùy chọn: Nếu Hoạt động muốn bắt đầu giao tiếp với các đoạn, nó chỉ có thể tham chiếu trực tiếp đến chúng và sau đó gọi một trong các phương pháp công khai của chúng.
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 Chánh
Các Fragment Chánh thực hiện người nghe từ Fragment trẻ em để nó có thể nhận tin nhắn từ nó.
TODO tùy chọn: Nếu Phân đoạn gốc muốn bắt đầu giao tiếp với Phân đoạn trẻ em, nó chỉ có thể tham chiếu trực tiếp đến nó và sau đó gọi một trong các phương pháp công khai của nó.
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;
}
}
Child Fragment
Các Fragment Child định nghĩa giao diện người nghe cho cả hoạt động và cho Fragment phụ huynh. Nếu Child Fragment chỉ cần giao tiếp với một trong số chúng, thì giao diện khác có thể bị loại bỏ.
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;
}
}
Bạn phải tạo phương thức Ví dụ về bố cục cha mẹ –
Bạn có thể thực hiện việc này bằng cách sử dụng ** Gọi lại ** trong ứng dụng của mình. –
Bạn cũng có tùy chọn sử dụng EventBus như [Otto] (http://square.github.io/otto/) hoặc [GreenRobot] (https://github.com/greenrobot/EventBus) –