1

I am completely new to Android and I have to submit this app to end my college degree, but I am having this problem where my fragment crashes my entire app.

To explain what I have done up until now is, I have a LoginActivity where I sent the userId through the Intent and have the id of the current user on my DashboardActivity (and I can display it), but in the DashboardActivity I have a bottom navigation bar that navigates to my FormFragment and my DataFragment.

Right now, want I would love to pass the userId value of the current user from the DashboardActivity to my DataFragment, so that I can display dynamically the user data according to the userId.

So with it, I found that the best option is to use bundle, but I don't now why (because I am completely new to this) my app crashes every time I switch from my FormFragment to my DataFragment.

Can you help me? I am desperate xD

This is my DashboardActivity code:

public class PainelActivity extends AppCompatActivity {

    private Button buttonLogout;
    private TextView textViewId;
    private Object DashboardFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_painel);
        BottomNavigationView navView = findViewById(R.id.nav_view);
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_home, R.id.navigation_dashboard)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        NavigationUI.setupWithNavController(navView, navController);

        // gets the id from the Intent
        Intent get = getIntent();
        String userId = get.getStringExtra(LoginActivity.EXTRA_ID);

        // Send the id to the Fragments
        Bundle bundle = new Bundle();
        bundle.putString("userId", userId);
        Fragment fragment = new Fragment();
        fragment.setArguments(bundle);
        getSupportFragmentManager().beginTransaction()
                .add(R.id.nav_host_fragment, fragment).commit();

        // see the id on the screen
        textViewId = findViewById(R.id.textViewId);
        textViewId.setText(userId);

        // logout
        buttonLogout = findViewById(R.id.logoutButton);
        buttonLogout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openMainActivity();
            }
        });
    }
    public void openMainActivity() {
        Intent HomePage = new Intent(this, MainActivity.class);
        startActivity(HomePage);

        Toast.makeText(PainelActivity.this, "Terminou a sua sessão.",
                Toast.LENGTH_LONG).show();
    }

}

And this is my DataFragment code:

public class DashboardFragment extends Fragment {
    INodeJS myAPI;
    private TextView textViewResult;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_dashboard, container, false);

        //Init API
        Retrofit retrofit = RetrofitClient.getInstance();
        myAPI = retrofit.create(INodeJS.class);
        textViewResult = root.findViewById(R.id.text_view_result);

        // gets the id from the activity
        if (getArguments() != null) {
            String userId = getArguments().getString("userId");
            int uid = Integer.parseInt(userId);

            Call<List<DataResult>> call = myAPI.executeGetData(uid);

            call.enqueue(new Callback<List<DataResult>>() {
                @Override
                public void onResponse(Call<List<DataResult>> call, Response<List<DataResult>> response) {
                    if (response.code() == 200) {
                        List<DataResult> DATA = response.body();

                        for (DataResult data: DATA) {
                            String content = "";
                            content += "Data: " +data.getDta() + "\n";
                            content += "Hora: " +data.getHora() + "\n";
                            content += "Glicémia: " +data.getIndiceGlicemia() + "\n";
                            content += "Insulina: " +data.getInsulina() + "\n";
                            content += "Medicação: " +data.getMedicacao() + "\n\n";

                            textViewResult.append(content);
                        }
                    }
                }

                @Override
                public void onFailure(Call<List<DataResult>> call, Throwable t) {
                    textViewResult.setText(t.getMessage());
                }
            });
        }

        return root;
    }
}

Thank you and have a nice day!

(I just edited my code and updated my question, right now, my app doesn't crash but I don't see the data.)

Abhimanyu
  • 11,351
  • 7
  • 51
  • 121
Francisco
  • 61
  • 3
  • 9

3 Answers3

5

While creating bundle:

Bundle bundle = new Bundle();
bundle.putString("userId", userId);
Fragment fragment = new Fragment();
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction()
            .replace(R.id.fragment_placeholder_id, dataFragment, "anyTagName").commit();

The To get the data in your fragment:

if (getArguments != null) {
    String userId = getArguments().getString("userId");
}
Priyank-py
  • 349
  • 3
  • 14
  • getSupportFragmentManager().beginTransaction().replace(R.id.fragment_placeholder_id, dataFragment, "anyTagName").commit(); what it does exactly? – Francisco Jun 06 '20 at 09:42
  • It return the FragmentManager for interacting with fragments associated with this activity. – Priyank-py Jun 06 '20 at 09:44
  • replace(R.id.fragment_placeholder_id Should this be my Activity then? – Francisco Jun 06 '20 at 09:45
  • .replace(R.id.DashboardActivity, DashboardFragment, "passData").commit(); Should it be like this? – Francisco Jun 06 '20 at 09:47
  • It should be the placeholder's id where you want the fragment. Placeholder in the xml layout of your activity. – Priyank-py Jun 06 '20 at 09:48
  • getSupportFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, (Fragment) DashboardFragment, "passData").commit(); I have it like this now, is it right? What's the tag for? Thank you so much for you patience explaining me this! – Francisco Jun 06 '20 at 09:55
  • I have to see your current activity's xml layout to say if it's right. Tag is like an Id that you have to explicitly provide when you want to use support-based Fragments from activity. Add any unique tag in string. – Priyank-py Jun 06 '20 at 10:03
3

When you create a new fragment you have an auto-generated function called newInstance.

So what you need to do is:

public static MyFragment newInstance(String param1, String param2) {
        MyFragment fragment = new MyFragment();
        Bundle args = new Bundle();
        args.putString("ARG_NAME", param1);
        args.putString("OTHER_ARG_NAME", param2);
        fragment.setArguments(args);
        return fragment;
}

Then, in your activity:

String str1 = "foo";
String str2 = "bar";
MyFragment myFragment = MyFragment.newInstance(str1, str2);
FragmentTransaction transaction = getSupportFragmentManager()
                                 .beginTransaction()
                                 .replace(R.id.nameOfActivityLayout, myFragment);
transaction.addToBackStack(null); // Add this line if you want to add the fragment to the back-stack
transaction.commit();

And back to your fragment, in your onCreate method :

String str1;
@Override
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            str1 = getArguments().getString("ARG_NAME");
        }
    }

The variable str1 will now have the value "foo" and you're free to use it in your fragment. Of course you can put other types in the bundle, like integers, booleans, arrays etc.

Yaron Grushka
  • 235
  • 2
  • 10
  • 1
    Is it really necessary to create a new instance? Because all I want is to pass the data (userId) to my existent fragments, I just want them to have access. This is way complicated than I thought geez xD – Francisco Jun 06 '20 at 10:11
  • 1
    Well I also thought it was complicated initially but it actually really isn't. Creating a new instance replaces your `Fragment fragment = new Fragment();`, it's just another way of creating an instance of that fragment, which supports passing arguments into it in an easy and convenient manner. – Yaron Grushka Jun 06 '20 at 10:46
1

You are using the jetpack navigation component, so its easier than before. You just have to pass the bundle to the navigation controller

Do:

navController.setGraph(R.navigation.graph, YOUR_BUNDLE);

then in your start fragment: Bundle b = getArguement(); String id = b.Get string("I'd");

Jason
  • 444
  • 4
  • 6