-1

In the app I'm working on I'm retrieving some data from a database. I have a tablayout with fragments on my activity and I need to push data to a specific tab. Because of the tabs I'm working with an ViewPagerAdapter; so the data goes from the MainActivity to the ViewPagerAdapter, to the fragment within a bundle. I think it's because that extra stop that I'm not getting the bundle to the fragment itself but I might be wrong.

The issue is when creating DescriptionTab.java and using getArguments().getString("Description"), getString()` is null, thus no data was revieved.

MainActivity.java

public class MainActivity extends AppCompatActivity {

    public String description;
    private TabLayout tabLayout;
    private ViewPager viewpager;

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

        description = "some text";
        tabLayout = findViewById(R.id.takenTabs);
        viewpager = findViewById(R.id.viewpager);

        setupViewPager(viewpager);

        tabLayout.setupWithViewPager(viewpager);
    }

    private void setupViewPager(ViewPager viewpager) {
        ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());

        Bundle bundle = new Bundle();
        bundle.putString("Description", description);
        Fragment fragmentDesc = new DescriptionTab();
        fragmentDesc.setArguments(bundle);

        viewPagerAdapter.addFragment(fragmentDesc, "Beschrijving"); // this line can crash
        viewPagerAdapter.addFragment(new UsersTab(), "Ingeschreven"); // this line can crash
        viewPagerAdapter.addFragment(new CommentsTab(), "Opmerkingen"); // this line can crash
        viewpager.setAdapter(viewPagerAdapter);
    }
}

I get the discription string from the database but to make it simpler right now I'm just creating it in the MainActivity. I do know for sure it actually retrieves data from the database, because it shows the data when I push it to a TextView. There's 3 tabs, but for now I'm only trying to pass data to the Description tab.

ViewPagerAdapter.java

public class ViewPagerAdapter extends FragmentPagerAdapter {

    private final ArrayList<Fragment> fragmentsList = new ArrayList<>(); // this line can crash
    private final ArrayList<String> fragmentTitle = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager fm) {
        super(fm); }

    @Override
    public Fragment getItem(int position) {
        return fragmentsList.get(position);
    }

    @Override
    public int getCount() {
        return fragmentsList.size();
    }

    public void addFragment(Fragment fragment, String tabTitle) {
        fragmentsList.add(fragment); // this line can crash
        fragmentTitle.add(tabTitle);
    }

    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        return fragmentTitle.get(position);
    }
}

I've tried creating the fragment and the bundle with the data in the addFragment() method before adding it to fragmentsList but that didn't work either.

DescriptionTab.java

public class DescriptionTab extends Fragment {
    
    public DescriptionTab() {
        // Required empty public constructor
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle state) {

        View rootView = inflater.inflate(R.layout.description_tab, container, false);

        final Bundle args = getArguments();
        final String description = args.getString("Description");

        TextView descriptionText = rootView.findViewById(R.id.descriptionTxt);
        descriptionText.setText(description);

        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.description_tab, container, false);
    }
}

getString("Description") is supposed to retrieve the data, but Android Studio already inspects it and tells me it may produce NullPointerException. I'm guessing it WILL produce NullPointerException because I can't find the issue in other parts of the code myself.

Please tell me, If you know what I'm doing wrong or why it's not working.

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
Amy
  • 1
  • 3
  • Is the value actually null or you are just getting the warning that it may be null? – Froyo Dec 03 '19 at 16:01
  • Also, your `onCreateView` function has an issue. You are inflating the view and setting the value. But you are returning another view (inflating again) and that's the view that will be used. You should return `rootView`. – Froyo Dec 03 '19 at 16:03
  • I used that `rootView` variable to be able to use findViewById, I barely paid attention to the view returned because that's part of the standard Fragment class when you make one in Android Studio. But thanks alot because returning `rootView` solved my issue :) Apparently the value wasn't really null, and yes it was just a warning. – Amy Dec 03 '19 at 19:16

2 Answers2

0

viewPagerAdapter.addFragment() is an anti-pattern because it will inevitably cause crashes after process death in production.

The correct way to implement a regular FragmentPagerAdapter is:

public class ViewPagerAdapter extends FragmentPagerAdapter {
    public ViewPagerAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
    }

    @Override
    public Fragment getItem(int position) {
        if(position == 0) return new RulesFragment();
        if(position == 1) return new TreeFragment();
        if(position == 2) return new PredictionFragment();

        throw new IllegalStateException("Unexpected position " + position);
    }

    @Override
    public int getCount() {
        return 3;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        if(position == 0) return "TREE RULES";
        if(position == 1) return "REGRESSION TREE";
        if(position == 2) return "PREDICTION";
      
        throw new IllegalStateException("Unexpected position " + position);
    }
}

To get a reference to a Fragment created by a ViewPager, use the following findFragmentByTag scheme:

Fragment fragment = supportFragmentManager.findFragmentByTag("android:switcher:" + viewPager.getId() + ":" + fragmentPosition)

To pass properties as a Bundle argument to the Fragment, it has to be passed to the instance created inside getItem().

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
-1

Try this

this.getArguments();

Code snippet

final Bundle args = this.getArguments();
Quick learner
  • 10,632
  • 4
  • 45
  • 55