두 조각 간의 기본 통신
하나 activity - MainActivity
있어요. 이 안에 Activity
두 fragments
가지가 있는데 둘 다 xml 내에서 선언적으로 생성했습니다.
String
사용자가 입력 한 Fragment A
텍스트를의 텍스트보기 로 전달하려고합니다 Fragment B
. 그러나 이것은 매우 어려운 것으로 입증되었습니다. 누구든지 내가 이것을 어떻게 얻을 수 있는지 알고 있습니까?
조각이 .NET을 사용하여 해당 활동에 대한 참조를 얻을 수 있다는 것을 알고 있습니다 getActivity()
. 그래서 거기서부터 시작할까요?
Android 개발자 페이지를 살펴보세요 : http://developer.android.com/training/basics/fragments/communicating.html#DefineInterface
기본적으로 Fragment A에 인터페이스를 정의하고 Activity가 해당 인터페이스를 구현하도록합니다. 이제 Fragment에서 인터페이스 메서드를 호출 할 수 있으며 Activity가 이벤트를 수신합니다. 이제 활동에서 두 번째 Fragment를 호출하여 수신 된 값으로 textview를 업데이트 할 수 있습니다.
활동이 인터페이스를 구현합니다 (아래 FragmentA 참조).
public class YourActivity implements FragmentA.TextClicked{
@Override
public void sendText(String text){
// Get Fragment B
FraB frag = (FragB)
getSupportFragmentManager().findFragmentById(R.id.fragment_b);
frag.updateText(text);
}
}
Fragment A는 인터페이스를 정의하고 필요할 때 메서드를 호출합니다.
public class FragA extends Fragment{
TextClicked mCallback;
public interface TextClicked{
public void sendText(String text);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (TextClicked) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement TextClicked");
}
}
public void someMethod(){
mCallback.sendText("YOUR TEXT");
}
@Override
public void onDetach() {
mCallback = null; // => avoid leaking, thanks @Deepscorn
super.onDetach();
}
}
조각 B에는 텍스트로 작업을 수행하는 공용 메서드가 있습니다.
public class FragB extends Fragment{
public void updateText(String text){
// Here you have it
}
}
다른 예 (심지어 일부 문서 이 글을 쓰는 시점에서)는 오래된 사용 onAttach
방법을. 다음은 전체 업데이트 된 예입니다.
메모
- 프래그먼트가 서로 또는 활동과 직접 대화하는 것을 원하지 않습니다. 이는 그것들을 특정 활동에 묶고 재사용을 어렵게 만듭니다.
- 해결책은 활동이 구현할 콜백 리스너 인터페이스를 만드는 것입니다. Fragment가 다른 Fragment 또는 상위 활동에 메시지를 보내려고 할 때 인터페이스를 통해이를 수행 할 수 있습니다.
- 활동이 자식 조각 공용 메서드와 직접 통신하는 것은 괜찮습니다.
- 따라서 Activity는 컨트롤러 역할을하여 한 조각에서 다른 조각으로 메시지를 전달합니다.
암호
MainActivity.java
public class MainActivity extends AppCompatActivity implements GreenFragment.OnGreenFragmentListener {
private static final String BLUE_TAG = "blue";
private static final String GREEN_TAG = "green";
BlueFragment mBlueFragment;
GreenFragment mGreenFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// add fragments
FragmentManager fragmentManager = getSupportFragmentManager();
mBlueFragment = (BlueFragment) fragmentManager.findFragmentByTag(BLUE_TAG);
if (mBlueFragment == null) {
mBlueFragment = new BlueFragment();
fragmentManager.beginTransaction().add(R.id.blue_fragment_container, mBlueFragment, BLUE_TAG).commit();
}
mGreenFragment = (GreenFragment) fragmentManager.findFragmentByTag(GREEN_TAG);
if (mGreenFragment == null) {
mGreenFragment = new GreenFragment();
fragmentManager.beginTransaction().add(R.id.green_fragment_container, mGreenFragment, GREEN_TAG).commit();
}
}
// The Activity handles receiving a message from one Fragment
// and passing it on to the other Fragment
@Override
public void messageFromGreenFragment(String message) {
mBlueFragment.youveGotMail(message);
}
}
GreenFragment.java
public class GreenFragment extends Fragment {
private OnGreenFragmentListener mCallback;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_green, container, false);
Button button = v.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String message = "Hello, Blue! I'm Green.";
mCallback.messageFromGreenFragment(message);
}
});
return v;
}
// This is the interface that the Activity will implement
// so that this Fragment can communicate with the Activity.
public interface OnGreenFragmentListener {
void messageFromGreenFragment(String text);
}
// This method insures that the Activity has actually implemented our
// listener and that it isn't null.
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnGreenFragmentListener) {
mCallback = (OnGreenFragmentListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnGreenFragmentListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mCallback = null;
}
}
BlueFragment.java
public class BlueFragment extends Fragment {
private TextView mTextView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_blue, container, false);
mTextView = v.findViewById(R.id.textview);
return v;
}
// This is a public method that the Activity can use to communicate
// directly with this Fragment
public void youveGotMail(String message) {
mTextView.setText(message);
}
}
XML
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<!-- Green Fragment container -->
<FrameLayout
android:id="@+id/green_fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginBottom="16dp" />
<!-- Blue Fragment container -->
<FrameLayout
android:id="@+id/blue_fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
fragment_green.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#98e8ba"
android:padding="8dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:text="send message to blue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
fragment_blue.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#30c9fb"
android:padding="16dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textview"
android:text="TextView"
android:textSize="24sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
가장 좋고 권장되는 방법은 공유 ViewModel을 사용하는 것입니다.
https://developer.android.com/topic/libraries/architecture/viewmodel#sharing
Google 문서에서 :
public class SharedViewModel extends ViewModel {
private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
public void select(Item item) {
selected.setValue(item);
}
public LiveData<Item> getSelected() {
return selected;
}
}
public class MasterFragment extends Fragment {
private SharedViewModel model;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
itemSelector.setOnClickListener(item -> {
model.select(item);
});
}
}
public class DetailFragment extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getSelected().observe(this, { item ->
// Update the UI.
});
}
}
추신 : 두 조각이 직접 통신하지 않습니다.
내 두 조각 A와 B를 고려하고 B에서 A로 데이터를 전달해야한다고 가정합니다.
그런 다음 B에 인터페이스를 만들고 데이터를 기본 활동에 전달합니다. 다른 인터페이스를 만들고 데이터를 조각 A로 전달합니다.
작은 예를 공유 :
조각 A는 다음과 같습니다.
public class FragmentA extends Fragment implements InterfaceDataCommunicatorFromActivity {
public InterfaceDataCommunicatorFromActivity interfaceDataCommunicatorFromActivity;
String data;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void updateData(String data) {
// TODO Auto-generated method stub
this.data = data;
//data is updated here which is from fragment B
}
@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
try {
interfaceDataCommunicatorFromActivity = (InterfaceDataCommunicatorFromActivity) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement TextClicked");
}
}
}
FragmentB는 다음과 같습니다.
class FragmentB extends Fragment {
public InterfaceDataCommunicator interfaceDataCommunicator;
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
// call this inorder to send Data to interface
interfaceDataCommunicator.updateData("data");
}
public interface InterfaceDataCommunicator {
public void updateData(String data);
}
@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
try {
interfaceDataCommunicator = (InterfaceDataCommunicator) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement TextClicked");
}
}
}
주요 활동은
public class MainActivity extends Activity implements InterfaceDataCommunicator {
public InterfaceDataCommunicatorFromActivity interfaceDataCommunicatorFromActivity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void updateData(String data) {
// TODO Auto-generated method stub
interfaceDataCommunicatorFromActivity.updateData(data);
}
public interface InterfaceDataCommunicatorFromActivity {
public void updateData(String data);
}
}
https://github.com/greenrobot/EventBus 또는 http://square.github.io/otto/를 살펴보십시오 .
또는 심지어 ... http://nerds.weddingpartyapp.com/tech/2014/12/24/implementing-an-event-bus-with-rxjava-rxbus/
아키텍처 구성 요소를 사용하여 활동 조각 간의 통신을 구현하는 간단한 방법이 있습니다. ViewModel 및 LiveData를 사용하여 활동 조각간에 데이터를 전달할 수 있습니다.
통신에 관련된 프래그먼트는 활동 라이프 사이클에 연결된 동일한 뷰 모델 객체를 사용해야합니다. 뷰 모델 객체는 데이터가 한 조각에 의해 전달되는 라이브 데이터 객체를 포함하고 두 번째 조각은 LiveData의 변경 사항을 수신하고 조각 1에서 보낸 데이터를 수신합니다.
완전한 예는 http://www.zoftino.com/passing-data-between-android-fragments-using-viewmodel을 참조하십시오 .
"setTargetFragment ()"알아보기
"startActivityForResult ()"가 두 활동 간의 관계를 설정하는 경우 "setTargetFragment ()"는 두 조각 간의 호출자 / 호출 관계를 정의합니다.
내 활동에 모든 조각이 사용할 수있는 인터페이스를 제공합니다. 동일한 활동에 많은 조각이있는 경우 이는 많은 코드 재 작성을 절약하고 유사한 기능을 가진 각 조각에 대한 개별 인터페이스를 만드는 것보다 더 깨끗한 솔루션 / 모듈 식입니다. 나는 또한 그것이 어떻게 모듈 식인지 좋아합니다. 단점은 일부 프래그먼트가 필요하지 않은 기능에 액세스 할 수 있다는 것입니다.
public class MyActivity extends AppCompatActivity
implements MyActivityInterface {
private List<String> mData;
@Override
public List<String> getData(){return mData;}
@Override
public void setData(List<String> data){mData = data;}
}
public interface MyActivityInterface {
List<String> getData();
void setData(List<String> data);
}
public class MyFragment extends Fragment {
private MyActivityInterface mActivity;
private List<String> activityData;
public void onButtonPress(){
activityData = mActivity.getData()
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof MyActivityInterface) {
mActivity = (MyActivityInterface) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement MyActivityInterface");
}
}
@Override
public void onDetach() {
super.onDetach();
mActivity = null;
}
}
최신 정보
이 대답을 무시하십시오. 작동하지 않는다는 것이 아닙니다. 그러나 더 나은 방법이 있습니다. 또한 Android는 프래그먼트 간의 직접 통신을 단호하게 권장합니다. 공식 문서를 참조하십시오 . 팁을 주신 @Wahib Ul Haq 사용자에게 감사드립니다.
원래 답변
글쎄, 당신은 조각 B에 개인 변수와 세터를 만들고 조각 A 자체에서 값을 설정할 수 있습니다.
FragmentB.java
private String inputString;
....
....
public void setInputString(String string){
inputString = string;
}
FragmentA.java
//go to fragment B
FragmentB frag = new FragmentB();
frag.setInputString(YOUR_STRING);
//create your fragment transaction object, set animation etc
fragTrans.replace(ITS_ARGUMENTS)
또는 질문에서 제안한대로 활동을 사용할 수 있습니다.
최근에 주석을 사용하여 유형 캐스팅 상용구 코드를 생성하는 라이브러리를 만들었습니다. https://github.com/zeroarst/callbackfragment
여기에 예가 있습니다. TextView
on을 클릭하면 DialogFragment
콜백이 트리거 MainActivity
된 onTextClicked
다음 MyFagment
상호 작용할 인스턴스를 가져옵니다 .
public class MainActivity extends AppCompatActivity implements MyFragment.FragmentCallback, MyDialogFragment.DialogListener {
private static final String MY_FRAGM = "MY_FRAGMENT";
private static final String MY_DIALOG_FRAGM = "MY_DIALOG_FRAGMENT";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager().beginTransaction()
.add(R.id.lo_fragm_container, MyFragmentCallbackable.create(), MY_FRAGM)
.commit();
findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyDialogFragmentCallbackable.create().show(getSupportFragmentManager(), MY_DIALOG_FRAGM);
}
});
}
Toast mToast;
@Override
public void onClickButton(MyFragment fragment) {
if (mToast != null)
mToast.cancel();
mToast = Toast.makeText(this, "Callback from " + fragment.getTag() + " to " + this.getClass().getSimpleName(), Toast.LENGTH_SHORT);
mToast.show();
}
@Override
public void onTextClicked(MyDialogFragment fragment) {
MyFragment myFragm = (MyFragment) getSupportFragmentManager().findFragmentByTag(MY_FRAGM);
if (myFragm != null) {
myFragm.updateText("Callback from " + fragment.getTag() + " to " + myFragm.getTag());
}
}
}
참고 URL : https://stackoverflow.com/questions/13700798/basic-communication-between-two-fragments
'IT박스' 카테고리의 다른 글
요소를 제거하기 전에 이벤트 리스너를 제거해야합니까? (0) | 2020.11.21 |
---|---|
“UseTaskFriendlySynchronizationContext”의 의미는 무엇입니까? (0) | 2020.11.21 |
html5 및 (canvas 또는 svg)를 사용하여 그리드를 그리는 방법 (0) | 2020.11.20 |
지시어의 '터미널'을 이해하는 방법? (0) | 2020.11.20 |
iOS의 NSURLErrorDomain 오류 코드 -999 (0) | 2020.11.20 |