Search code examples
androidjsonandroid-fragmentsandroid-viewpagerandroid-tablayout

Fetching JSON data returns null in fragment of a tablayout


My DynamicFragment.java is as below

public class DynamicFragment extends Fragment {

public static DynamicFragment newInstance() {
    return new DynamicFragment();
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

// adding the layout with inflater
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_dynamic, container, false);
    initViews(view);
    return view;
}

// initialise the categories
private void initViews(View view) {
    TextView textView = view.findViewById(R.id.commonTextView);
    textView.setText(String.valueOf("Category : " + getArguments().getInt("position")));

    TextView userName = view.findViewById(R.id.userName);
    userName.setText("Name :" + getArguments().getString("name"));

}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
}

// pause function call
@Override
public void onPause() {
    super.onPause();
}

// resume function call
@Override
public void onResume() {
    super.onResume();
}

// stop when we close
@Override
public void onStop() {
    super.onStop();
}

// destroy the view
@Override
public void onDestroyView() {
    super.onDestroyView();
}

@Override
public void onDestroy() {
    super.onDestroy();
  }
}

DynamicFragmentAdapter.java is below:

public class DynamicFragmentAdapter extends FragmentStatePagerAdapter {
private int mNumOfTabs;

DynamicFragmentAdapter(FragmentManager fm, int NumOfTabs) {
    super(fm);
    this.mNumOfTabs = NumOfTabs;
}

// get the current item with position number
@Override
public Fragment getItem(int position) {
    Bundle b = new Bundle();
    b.putInt("position", position);
    Fragment frag = DynamicFragment.newInstance();
    frag.setArguments(b);
    return frag;
}

// get total number of tabs
@Override
public int getCount() {
    return mNumOfTabs;
}
}

DynamicActivity.java is as below:

public class DynamicActivity extends AppCompatActivity {

private ViewPager viewPager;
private TabLayout mTabLayout;

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

private void initViews() {

    // initialise the layout
    viewPager = findViewById(R.id.viewpager);
    mTabLayout = findViewById(R.id.tabs);

    // setOffscreenPageLimit means number
    // of tabs to be shown in one page
    viewPager.setOffscreenPageLimit(5);
    viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
    mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            // setCurrentItem as the tab position
            viewPager.setCurrentItem(tab.getPosition());
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });
    setDynamicFragmentToTabLayout();
}

// show all the tab using DynamicFragmnetAdapter
private void setDynamicFragmentToTabLayout() {

    try {
        // get JSONObject from JSON file
        JSONObject obj = new JSONObject(loadJSONFromAsset());
        // fetch JSONArray named contacts
        JSONArray userArray = obj.getJSONArray("contacts");
        int arrayLength = userArray.length();

        // implement for loop for getting users list data
        for (int i = 0; i < arrayLength; i++) {

            // create a JSONObject for fetching single user data
           JSONObject userDetail = userArray.getJSONObject(i);
            // fetch name and store it in arraylist
           
            MainActivity.personNames.add(userDetail.getString("name"));

            // set the tab name as "Page: " + i
            mTabLayout.addTab(mTabLayout.newTab().setText("Page:" + i));

        }
    } catch (JSONException e) {
        e.printStackTrace();
    }

    DynamicFragmentAdapter mDynamicFragmentAdapter = new DynamicFragmentAdapter(getSupportFragmentManager(), mTabLayout.getTabCount());

    // set the adapter
    viewPager.setAdapter(mDynamicFragmentAdapter);

    // set the current item as 0 (when app opens for first time)
    viewPager.setCurrentItem(0);

}

public String loadJSONFromAsset() {
    String json = null;
    try {
        InputStream is = getAssets().open("contact_data.json");
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        json = new String(buffer, "UTF-8");
    } catch (IOException ex) {
        ex.printStackTrace();
        return null;
    }
    return json;
}
}

The name does not load from JSON and shows as "null" in fragment though I've defined the TextView userName in fragment_dynamic.xml as below

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">

<TextView
    android:id="@+id/commonTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="zxjhcvzxvchjzxbhj"
    android:textColor="@color/purple_500"
    android:textStyle="bold" />
<TextView
    android:id="@+id/userName"
    android:layout_below="@id/commonTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="zxjhcvzxvchjzxbhj"
    android:textColor="@color/purple_500"
    android:textStyle="bold" />

</RelativeLayout>

My truncated contacts.json is as below:

    {
  "contacts": [

{
  "id": "1",
  "name": "Amitabh"
  "age": "25"
},

{
  "id": "2",
  "name": "Amit"
  "age": "30"
  }  
 ]
 }

The position number of the tab updates correctly as I swipe through the fragments, from the FOR Loop but the name shows as "null" in all the fragments. I am new to the JSON concepts and its use in Fragments and Tablayouts. Any help in this regard will be of great help.

I think the variable names in my JSON data are not linked with the variables in the java class and don't know how to do it.

Thanks in advance!


Solution

  • Try to store the personNames in a local variable and pass it to the adapter:

        ArrayList<String> personNames = new ArrayList<String>()
        
        try {
            // get JSONObject from JSON file
            JSONObject obj = new JSONObject(loadJSONFromAsset());
            // fetch JSONArray named contacts
            JSONArray userArray = obj.getJSONArray("contacts");
            int arrayLength = userArray.length();
    
            // implement for loop for getting users list data
            for (int i = 0; i < arrayLength; i++) {
    
                // create a JSONObject for fetching single user data
               JSONObject userDetail = userArray.getJSONObject(i);
                // fetch name and store it in arraylist
               
                personNames.add(userDetail.getString("name"));
    
                // set the tab name as "Page: " + i
                mTabLayout.addTab(mTabLayout.newTab().setText("Page:" + i));
    
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    
        DynamicFragmentAdapter mDynamicFragmentAdapter = new DynamicFragmentAdapter(getSupportFragmentManager(), mTabLayout.getTabCount(), personNames);
    
        // set the adapter
        viewPager.setAdapter(mDynamicFragmentAdapter);
    

    Then, from the adapter, pass the name argument down to the DynamicFragment:

    public class DynamicFragmentAdapter extends FragmentStatePagerAdapter {
        private int mNumOfTabs;
        private ArrayList<String> personNames;
    
        DynamicFragmentAdapter(FragmentManager fm, int NumOfTabs, ArrayList<String> personNames) {
            super(fm);
            this.mNumOfTabs = NumOfTabs;
            this.personNames = personNames;
        }
    
        // get the current item with position number
        @Override
        public Fragment getItem(int position) {
            Bundle b = new Bundle();
            b.putInt("position", position);
            b.putString("name", personNames[position])
            Fragment frag = DynamicFragment.newInstance();
            frag.setArguments(b);
            return frag;
        }
    

    Finally, you should be able to access the name in the Fragment using (like you where doing):

    getArguments().getString("name")