0

I'm doing some tests with fragments to study about it. And I have a doubt.

I have a main activity with a toolbar with only one item and when this item is clicked I add a fragment A that has a list view.

Then I click in one item of the list view, the fragment A is removed and its fragment B is replace to fragment A. Fragment B has a textview to show the text of the clicked item on the fragment A.

To pass the data of the clicked item on the list view in fragment A to the textview of the fragment B I need also to add a button on the fragment B xml, and when this button is clicked the data of the clicked item is sent to the fragment B and the textview is updated with the correct clicked item text.

But its not possible to do this automatically? If this method “sendDataToFragmentB(View view)” is called on the addText(String text) method It appears a NullPointerException in FragmentB.addText(java.lang.String). But If I have the button in the fragmentb xml with the onClick="sendDataTofragmentB" when the button is clicked it works.

Interface:

public interface Listener {
    public void addText(String text);
}

main activity

public class MainActivity extends AppCompatActivity implements Listener {

    Toolbar toolbar;
    FragmentManager manager;
    private String text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        manager = getFragmentManager();

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        getSupportActionBar().setTitle("Pets");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        String msg = "";

        if (item.getItemId() == R.id.search) {
                msg = "search";
                AddFragmentA();
        }
        Toast.makeText(this, msg + "clicked !", Toast.LENGTH_SHORT).show();
        return super.onOptionsItemSelected(item);
    }
    @Override
    public void addText(String text) {
        this.text = text;

        Toast.makeText(this, "Text Received in Activity" + text, Toast.LENGTH_SHORT).show();
        sendDataToFragmentB();
    }
    public void sendDataToFragmentB(View view) {

            FragmentB fragmentB = (FragmentB) manager.findFragmentByTag("fragB");
            fragmentB.addText(text);

    }
}

fragment A:

public class FragmentA extends Fragment {
    private static final String TAG = FragmentA.class.getSimpleName();
    private ListView listItems;

    private String[] items = {
            "item1",
            "item2",
    };

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_a, container, false);
        listItems = (ListView) view.findViewById(R.id.listviewInFragment);

        ArrayAdapter<String> adapter =
                new ArrayAdapter<String>(getActivity().getApplicationContext(),
                        android.R.layout.simple_list_item_1, android.R.id.text1, items);
        listItems.setAdapter(adapter);

        listItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                int positionCode = i;
                String clickedValue = (String) adapterView.getItemAtPosition(i);

                Listener listener = (Listener) getActivity();
                listener.addText(clickedValue);

                Toast.makeText(getActivity().getApplicationContext(), clickedValue, Toast.LENGTH_SHORT).show();
                removeFragmentA();
                AddFragmentB();
            }

        });

        return view;
    }

    public void removeFragmentA(){
        FragmentA fragmentA = (FragmentA) getFragmentManager().findFragmentByTag("fragA");
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        if(fragmentA !=null){
            transaction.remove(fragmentA);
            transaction.commit();
        }
        else{
            Toast.makeText(this.getActivity(), "Fragment A not found", Toast.LENGTH_SHORT).show();
        }
    }
    public void AddFragmentB(){

        FragmentB fragmentB = new FragmentB();
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.add(R.id.container, fragmentB, "fragB");
        transaction.commit();
    }
}

fragment B:

public class FragmentB extends Fragment {
    private TextView txvResult;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_b, container, false);
        txvResult = (TextView) view.findViewById(R.id.txvResult);
        return view;
    }
    public void addText(String text){
        String result = text;
        txvResult.setText(result);
    }
}
  • Though there's another issue that will affect this, you should at least try to reason through your code as you have it now. In `onItemClick()`, look at the order of things. Do you really want to call `listener.addText()` before you've even swapped out the `Fragment`s? Before the `FragmentB` instance is even created? – Mike M. Oct 15 '17 at 23:50
  • Instead of a listener, who not send the data in a bundle and access it directly there – Aniruddha K.M Oct 15 '17 at 23:57
  • Thanks. Also the same issue with bundle. But the issue is on the onCreateView method in String text = getArguments().getString("clickedValue"); –  Oct 16 '17 at 00:12

2 Answers2

0

Short answer: You want to use Bundles. You can try something like this

public void AddFragmentB(String clickedText){


    FragmentB fragmentB = new FragmentB();

    Bundle bundle = new Bundle();
    bundle.putString(R.string.clicked_text_key, clickedText);
    fragmentB.setArguments(bundle);

    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.add(R.id.container, fragmentB, "fragB");
    transaction.commit();
}

FragmentB

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

    addText();

    return view;
}
public void addText(){
    String result = getArguments().getString(R.string.clicked_text_key);
    txvResult.setText(result);
}

See: How to transfer some data to another Fragment?

Mars
  • 2,505
  • 17
  • 26
  • Thanks, but also dont works. It appears null obect reference on widget.TetView.setTex(). –  Oct 16 '17 at 09:41
  • addText() needs to be called after fragmentB.onCreateView(), or possibly in it (after connecting txvResult) – Mars Oct 17 '17 at 01:14
  • I edited the answer so that you can see the usage--my guess is you were calling addText before the view had been inflated, meaning txvResult would be null. – Mars Oct 17 '17 at 01:31
0

You can try with StickyEvent in EventBus Sticky Event. When item is clicked, just post a sticky event like

EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));

Then after adding FragmentB, you can receive the event in the subscribe method.

Kingfisher Phuoc
  • 8,052
  • 9
  • 46
  • 86