2

My app have one activity A and two fragments F1 and F2.

One clicking button in F1, the F1 is replaced by F2. I want to transfer data in F1 to F2. For that I implemented the interface in F1 and override its method in A.

But when sending the data from A to F2, my reference(sFragment in code A) to the F2 remains null,due to which data is not sent to F2. I am getting reference to the F2 using TAG provided while replacing F1 by F2.

Does it have something to do with the lifecycle like when I am trying to get reference to the F2 it hasn't yet created?

F1

 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){

    View v = inflater.inflate(R.layout.form_fragment1,container,false); 
    nextB = (Button) v.findViewById(R.id.f1Next);
    nextB.setOnClickListener(this);
    return v;
}

@Override
public void onClick(View view) {
    switch (view.getId()){

        case R.id.f1Next:
            SFragment fragment = new SFragment();
            FragmentManager mManager = getFragmentManager();
            FragmentTransaction mTransaction = mManager.beginTransaction();
            mTransaction.replace(R.id.fragment_container,fragment,"SecondF"); // SecondF
            mTransaction.addToBackStack(null);  // this is required to move to the previous fragment
            mTransaction.commit();
            commListener.PlaceName(data1,data2);  //passing value to activity
            break;

    }

}
interface CommBridge{

    void PlaceName(String data1,String data2);
}

@Override
public void onAttach(Context context){
    super.onAttach(context);
    if (context instanceof CommBridge){
        commListener= (CommBridge) context;
    }
}

}

A

 @Override
public void PlaceName(String data1, String data2) {
    SFragment sFragment=(SFragment) getFragmentManager().findFragmentByTag("SecondF");
    if (sFragment != null && sFragment.isInLayout()){
        Log.d("STATE","1");
        sFragment.setPlace(data1,data2);
    }else{
        Log.d("STATE","2");  // this is always  the case
    }

F2

public class SFragment extends Fragment {
String Place2,Place1;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
    View v = inflater.inflate(R.layout.form_fragment2,container,false);
    return v;
}

void setPlace(String data1, String data2){
    place1 = data1;
    place2 =  data2;

}
}
Gaurav Singh
  • 125
  • 3
  • 12

2 Answers2

2

Let the activity be responsible for handling the onClick event of the Fragment. See the example below.

Activity:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

public class MainActivity extends AppCompatActivity implements Fragment1.CommBridge {


    private Fragment1 fragment1 = new Fragment1();
    private Fragment2 fragment2 = new Fragment2();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.content, fragment1)
                .commit();


    }

    @Override
    public void onButtonClicked(String data1, String data2) {
        fragment2.setData(data1, data2);
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.content, fragment2)
                .commit();
    }
}

Fragment1:

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

public class Fragment1 extends Fragment {

    interface CommBridge {
        void onButtonClicked(String data1, String data2);
    }

    private CommBridge handler;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof CommBridge) {
            handler = (CommBridge) context;
        }
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1, container, false);

        Button button = (Button) view.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.onButtonClicked("Data1", "Data2");
            }
        });

        return view;
    }
}

Fragment2

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class Fragment2 extends Fragment {

    private String data1;
    private String data2;

    public void setData(String data1, String data2) {
        this.data1 = data1;
        this.data2 = data2;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment2, container, false);

        TextView textView = (TextView) view.findViewById(R.id.textView);
        textView.setText(data1 + "\n" + data2);

        return view;
    }
}
0

I would recommend putting the code for replacing the fragment in your Activity and put the values which should be passed to SFragment() in its arguments directly:

SFragment newFragment = new SFragment();
Bundle args = new Bundle();
args.putString("place1", data1);
args.putString("place2", data1);
newFragment.setArguments(args);

You could get them in SFragment#onCreateView()

String place1 = getArguments().getString("place1");

Also have a look here: https://developer.android.com/training/basics/fragments/communicating.html

mbo
  • 4,611
  • 2
  • 34
  • 54
  • This solved my problem Marius. But why you recommended me to put the replacing code in Activity?Also Isn't it the case of direct communication between fragments which should be avoided? – Gaurav Singh Jul 20 '17 at 14:29
  • The Activity should be in control and manage it's Fragments. The specific Fragment should literally not know that there's another Fragment. Then when you want to replace a Fragment, you only have to touch the controlling Activity and not search in every Fragment. – mbo Jul 20 '17 at 14:53
  • In my understanding direct communication is only if you try to call methods of a Fragment from another Fragment. Passing arguments over the controlling Activity is the common way to communicate. – mbo Jul 20 '17 at 14:57