[android] 조각간에 데이터를 전달하는 방법

내 프로그램에서 두 개의 fragmen간에 데이터를 전달하려고합니다. List에 저장되는 단순한 문자열입니다. 목록은 조각 A에서 공개되며 사용자가 목록 항목을 클릭하면 조각 B에 표시되어야합니다. 콘텐츠 제공자는 ID 만 지원하는 것 같아서 작동하지 않습니다. 어떤 제안?



답변

번들을 사용하지 않으시겠습니까? 첫 번째 조각에서 설정하는 방법은 다음과 같습니다.

Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putInt(key, value);
fragment.setArguments(bundle);

그런 다음 두 번째 Fragment에서 다음을 사용하여 데이터를 검색합니다.

Bundle bundle = this.getArguments();
int myInt = bundle.getInt(key, defaultValue);

번들에는 많은 데이터 유형에 대한 put 메소드가 있습니다. http://developer.android.com/reference/android/os/Bundle.html을 참조 하십시오.


답변

Roboguice를 사용하는 경우 Roboguice의 EventManager를 사용하여 Activity를 인터페이스로 사용하지 않고도 데이터를 전달할 수 있습니다. 이것은 아주 깨끗한 IMO입니다.

Roboguice를 사용하지 않는 경우 Otto도 이벤트 버스로 사용할 수 있습니다. http://square.github.com/otto/

업데이트 20150909 : 이제 Green Robot Event Bus 또는 RxJava도 사용할 수 있습니다. 사용 사례에 따라 다릅니다.


답변

로부터 Fragment 문서 :

예를 들어 사용자 이벤트를 기반으로 콘텐츠를 변경하기 위해 종종 하나의 Fragment가 다른 Fragment와 통신하기를 원할 것입니다. 모든 Fragment-to-Fragment 통신은 관련 활동을 통해 이루어집니다. 두 조각은 직접 통신해서는 안됩니다.

그래서 나는 당신이 문서 에서 기본적인 조각 훈련 문서 를 살펴 보길 권한다 . 예제와 둘러보기 가이드로 꽤 포괄적입니다.


답변

따라서 Frag A와 Fragment B를 제어하는 ​​Activity AB가 있다고 가정 해 보겠습니다. Fragment A 내부에는 Activity AB가 구현할 수있는 인터페이스가 필요합니다. 샘플 Android 코드에는 다음이 있습니다.

private Callbacks mCallbacks = sDummyCallbacks;

/ *이 조각을 포함하는 모든 활동이 구현해야하는 콜백 인터페이스. 이 메커니즘을 사용하면 활동에 항목 선택을 알릴 수 있습니다. * /

public interface Callbacks {
/*Callback for when an item has been selected. */
      public void onItemSelected(String id);
}

/*A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity. */
private static Callbacks sDummyCallbacks = new Callbacks() {
    @Override
    public void onItemSelected(String id) {
    }
};

콜백 인터페이스는 프래그먼트 중 하나에 배치됩니다 (Fragment A라고 가정 해 보겠습니다). 이 콜백 인터페이스의 목적은 모든 활동이 구현할 수있는 Frag A 내부의 중첩 클래스와 같다고 생각합니다. 따라서 Fragment A가 TV 인 경우 CallBack은 Fragment A를 Activity AB에서 사용할 수있는 TV 리모컨 (인터페이스)입니다. 나는 멍청이이기 때문에 세부 사항에 대해 틀릴 수 있지만 프로그램이 모든 화면 크기에서 완벽하게 작동하도록 만들었으며 이것이 내가 사용한 것입니다.

따라서 Fragment A 내부에는 다음이 있습니다. (Android의 샘플 프로그램에서 가져 왔습니다.)

@Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
//mCallbacks.onItemSelected( PUT YOUR SHIT HERE. int, String, etc.);
//mCallbacks.onItemSelected (Object);
}

그리고 Activity AB 내에서 onItemSelected 메서드를 재정의합니다.

public class AB extends FragmentActivity implements ItemListFragment.Callbacks {
//...
@Override
//public void onItemSelected (CATCH YOUR SHIT HERE) {
//public void onItemSelected (Object obj) {
    public void onItemSelected(String id) {
    //Pass Data to Fragment B. For example:
    Bundle arguments = new Bundle();
    arguments.putString(“FragmentB_package”, id);
    FragmentB fragment = new FragmentB();
    fragment.setArguments(arguments);
    getSupportFragmentManager().beginTransaction().replace(R.id.item_detail_container, fragment).commit();
    }

따라서 Activity AB 내에서 기본적으로 모든 것을 Bundle에 넣고 B에 전달합니다. Bundle을 사용하는 방법을 잘 모르는 경우 클래스를 찾아보십시오.

기본적으로 Android가 제공 한 샘플 코드를 사용합니다. DummyContent 물건이있는 사람. 새로운 Android 애플리케이션 패키지를 만들면 MasterDetailFlow라는 제목의 패키지입니다.


답변

1- 첫 번째 방법은 인터페이스를 정의하는 것입니다.

public interface OnMessage{
    void sendMessage(int fragmentId, String message);
}

public interface OnReceive{
    void onReceive(String message);
}

2- 활동에서 OnMessage 인터페이스 구현

public class MyActivity implements OnMessage {
   ...
   @Override
   public void sendMessage(int fragmentId, String message){
       Fragment fragment = getSupportFragmentManager().findFragmentById(fragmentId);
       ((OnReceive) fragment).sendMessage();
   }
}

3- 조각에서 OnReceive 인터페이스 구현

public class MyFragment implements OnReceive{
    ...
    @Override
    public void onReceive(String message){
        myTextView.setText("Received message:" + message);
    }
}

이것은 프래그먼트 간 메시지 전달을 처리하는 표준 버전입니다.

프래그먼트 간 데이터 전달을 처리하는 또 다른 방법은 이벤트 버스를 사용하는 것입니다.

1- 이벤트 버스에 등록 / 등록 취소

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
}

2- 이벤트 클래스 정의

public class Message{
    public final String message;

    public Message(String message){
        this.message = message;
    }
}

3- 응용 프로그램의 어느 곳에 나이 이벤트를 게시하십시오.

EventBus.getDefault().post(new Message("hello world"));

4- 해당 이벤트를 구독하여 조각으로 받으십시오.

@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(Message event){
    mytextview.setText(event.message);
}

자세한 내용, 사용 사례 및 이벤트 버스 패턴에 대한 예제 프로젝트 .


답변

제 경우에는 FragmentB-> FragmentA에서 데이터를 거꾸로 보내야 했으므로 조각이 이미 초기화되었으므로 Intents는 옵션이 아니 었 습니다. 위의 모든 답변이 좋게 들리지만 구현 하는 데 많은 보일러 플레이트 코드가 필요 하므로 LocalBroadcastManager 를 사용 하는 훨씬 더 간단한 접근 방식 을 사용 했습니다. 위에서 말한대로 정확하게 수행하지만 불쾌한 상용구 코드가 없습니다. 아래에 예가 나와 있습니다.

조각을 보내는 중 (조각 B)

public class FragmentB {

    private void sendMessage() {
      Intent intent = new Intent("custom-event-name");
      intent.putExtra("message", "your message");
      LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }
 }

수신 할 메시지 조각 (FRAGMENT A)

  public class FragmentA {
    @Override
    public void onCreate(Bundle savedInstanceState) {

      ...

      // Register receiver
      LocalBroadcastManager.getInstance(this).registerReceiver(receiver,
          new IntentFilter("custom-event-name"));
    }

//    This will be called whenever an Intent with an action named "custom-event-name" is broadcasted.
    private BroadcastReceiver receiver = new BroadcastReceiver() {
      @Override
      public void onReceive(Context context, Intent intent) {
        String message = intent.getStringExtra("message");
      }
    };
}

누군가에게 도움이되기를 바랍니다.


답변

그것은 조각의 구조에 달려 있습니다. Fragment Class B 정적 및 대상 TextView 객체 정적에 대한 일부 메서드를 가질 수있는 경우 Fragment Class A에서 직접 메서드를 호출 할 수 있습니다. 메서드가 즉시 수행되므로 리스너보다 낫습니다. 활동 전반에 걸쳐 청취를 수행하는 추가 작업이 필요합니다. 아래 예를 참조하십시오.

Fragment_class_B.setmyText(String yourstring);

조각 B에서는 다음과 같이 정의 된 메서드를 가질 수 있습니다.

public static void setmyText(final String string) {
myTextView.setText(string);
}

Fragment B에서 myTextView를 정적으로 설정하고 Fragment A에서 Fragment B 클래스를 올바르게 가져 오는 것을 잊지 마십시오.

최근에 내 프로젝트에서 절차를 수행했고 효과가있었습니다. 도움이 되었기를 바랍니다.