How to pass data between fragments

2018-12-31 08:28发布

Im trying to pass data between two fragmens in my program. Its just a simple string that is stored in the List. The List is made public in fragments A, and when the user clicks on a list item, I need it to show up in fragment B. The content provider only seems to support ID's, so that will not work. Any suggestions?

13条回答
临风纵饮
2楼-- · 2018-12-31 08:55

I think communication between fragments should be done via activity. And communication between fragment and activity can be done this way: https://developer.android.com/training/basics/fragments/communicating.html https://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity

查看更多
明月照影归
3楼-- · 2018-12-31 08:56

That depends on how the fragment is structured. If you can have some of the methods on the Fragment Class B static and also the target TextView object static, you can call the method directly on Fragment Class A. This is better than a listener as the method is performed instantaneously, and we don't need to have an additional task that performs listening throughout the activity. See example below:

Fragment_class_B.setmyText(String yourstring);

On Fragment B you can have the method defined as:

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

Just don't forget to have myTextView set as static on Fragment B, and properly import the Fragment B class on Fragment A.

Just did the procedure on my project recently and it worked. Hope that helped.

查看更多
流年柔荑漫光年
4楼-- · 2018-12-31 08:59

I'm working on a similar project and I guess my code may help in the above situation

Here is the overview of what i'm doing

My project Has two fragments Called "FragmentA" and "FragmentB"

-FragmentA Contains one list View,when you click an item in FragmentA It's INDEX is passed to FragmentB using Communicator interface

  • The design pattern is totally based on the concept of java interfaces that says "interface reference variables can refer to a subclass object"
  • Let MainActivity implement the interface provided by fragmentA(otherwise we can't make interface reference variable to point to MainActivity)
  • In the below code communicator object is made to refer to MainActivity's object by using "setCommunicator(Communicatot c)" method present in fragmentA.
  • I'm triggering respond() method of interface from FrgamentA using the MainActivity's reference.

    Interface communcator is defined inside fragmentA, this is to provide least access previlage to communicator interface.

below is my complete working code

FragmentA.java

public class FragmentA extends Fragment implements OnItemClickListener {

ListView list;
Communicator communicater;


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    return inflater.inflate(R.layout.fragmenta, container,false);
}

public void setCommunicator(Communicator c){
    communicater=c;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onActivityCreated(savedInstanceState);
    communicater=(Communicator) getActivity();
    list = (ListView) getActivity().findViewById(R.id.lvModularListView);
    ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(),
            R.array.items, android.R.layout.simple_list_item_1);
    list.setAdapter(adapter);
    list.setOnItemClickListener(this);

}

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) {
communicater.respond(index);

}

public interface Communicator{
    public void respond(int index);
}

}

fragmentB.java

public class FragmentA extends Fragment implements OnItemClickListener {

ListView list;
Communicator communicater;


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    return inflater.inflate(R.layout.fragmenta, container,false);
}

public void setCommunicator(Communicator c){
    communicater=c;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onActivityCreated(savedInstanceState);
    communicater=(Communicator) getActivity();
    list = (ListView) getActivity().findViewById(R.id.lvModularListView);
    ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(),
            R.array.items, android.R.layout.simple_list_item_1);
    list.setAdapter(adapter);
    list.setOnItemClickListener(this);

}

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) {
communicater.respond(index);

}

public interface Communicator{
    public void respond(int index);
}

}

MainActivity.java

public class MainActivity extends Activity implements FragmentA.Communicator {
FragmentManager manager=getFragmentManager();
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FragmentA fragA=(FragmentA) manager.findFragmentById(R.id.fragmenta);
    fragA.setCommunicator(this);


}

@Override
public void respond(int i) {
    // TODO Auto-generated method stub

FragmentB FragB=(FragmentB) manager.findFragmentById(R.id.fragmentb);
FragB.changetext(i);
}



}
查看更多
素衣白纱
5楼-- · 2018-12-31 09:02

Why don't you use a Bundle. From your first fragment, here's how to set it up:

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

Then in your second Fragment, retrieve the data using:

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

Bundle has put methods for lots of data types. Please see http://developer.android.com/reference/android/os/Bundle.html

查看更多
余生请多指教
6楼-- · 2018-12-31 09:03

IN my case i had to send the data backwards from FragmentB->FragmentA hence Intents was not an option as the fragment would already be initialised All though all of the above answers sounds good it takes a lot of boiler plate code to implement, so i went with a much simpler approach of using LocalBroadcastManager, it exactly does the above said but without alll the nasty boilerplate code. An example is shared below.

In Sending Fragment(Fragment B)

public class FragmentB {

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

And in the Message to be Received Fragment(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");
      }
    };
}

Hope it helps someone

查看更多
初与友歌
7楼-- · 2018-12-31 09:05

1- The first way is define an interface

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

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

2- In you activity implement OnMessage interface

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

3- In your fragment implement OnReceive interface

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

This is the boilerplate version of handling message passing between fragments.

Another way of handing data passage between fragments are by using an event bus.

1- Register/unregister to an event bus

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

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

2- Define an event class

public class Message{
    public final String message;

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

3- Post this event in anywhere in your application

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

4- Subscribe to that event to receive it in your Fragment

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

For more details, use cases, and an example project about the event bus pattern.

查看更多
登录 后发表回答