Search code examples
androidarraylistandroid-arrayadaptercustom-adapter

Using one adapter for multiple arrays


I have a situation I need some advice on. I have an app that has an expandable list view. Each child click sends the user to the next activity, which is a tab layout with a list view. The tab layout has 3 tabs. I'm trying to figure out how to send data to the 3 tabs listviews when child is clicked on expandable listview.

Originally I was going to set it up in the setOnChildClickListener like so:

expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
        @Override
        public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
            if (groupPosition == 0) {
                if (childPosition == 0) {
                    mCustomListViewAdapter.addAdapterItem(new CustomObject("Squats", "60%", "6", "150", false));
                    listViewFri.setAdapter(mCustomListViewAdapter);

EDIT: this is my tablayout activity that sets up the 3 tabs. I'm not sure where to access the bundled extras.

public class WorkoutDaysActivity extends BaseActivity {

ListView listViewFri = (ListView) findViewById(R.id.listViewFri);
ListView listViewMon = (ListView) findViewById(R.id.listViewMon);
ListView listViewWed = (ListView) findViewById(R.id.listViewWed);

/**
 * The {@link android.support.v4.view.PagerAdapter} that will provide
 * fragments for each of the sections. We use a
 * {@link FragmentPagerAdapter} derivative, which will keep every
 * loaded fragment in memory. If this becomes too memory intensive, it
 * may be best to switch to a
 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
 */
private SectionsPagerAdapter mSectionsPagerAdapter
/**
 * The {@link ViewPager} that will host the section contents.
 */



private ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.workout_days);
    Bundle extras = getIntent().getBundleExtra("args");



    mToolBar = activateToolbarWithHomeEnabled();
    setUpNavigationDrawer();

    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.
    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mSectionsPagerAdapter);

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(mViewPager);



}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_workout_days, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";

    public PlaceholderFragment() {
    }

    /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

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



        switch (getArguments().getInt(ARG_SECTION_NUMBER)) {
            case 1:
                View rootView = inflater.inflate(R.layout.fragment_workout_days, container, false);

                Bundle extras = getArguments();
                CustomObject objects = (CustomObject) extras.getSerializable("w29w1");




                return rootView;
            case 2: View rootView2 = inflater.inflate(R.layout.fragment_sub_page1, container, false);
                TextView textView2 = (TextView) rootView2.findViewById(R.id.textView2);
                textView2.setText("Workout 29 Week 1");
                return rootView2;
            case 3:
                View rootView3 = inflater.inflate(R.layout.fragment_sub_page2, container, false);
                TextView textView3 = (TextView) rootView3.findViewById(R.id.txtFrag3);
                textView3.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
                return rootView3;
            default: View rootView4 = inflater.inflate(R.layout.fragment_workout_days, container, false);
                TextView textView4 = (TextView) rootView4.findViewById(R.id.txtFrag1);
                textView4.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
                return rootView4;
        }

    }
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
 * one of the sections/tabs/pages.
 */
public class SectionsPagerAdapter extends FragmentPagerAdapter {

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

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a PlaceholderFragment (defined as a static inner class below).
        return PlaceholderFragment.newInstance(position + 1);
    }

    @Override
    public int getCount() {
        // Show 3 total pages.
        return 3;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return "Monday";
            case 1:
                return "Wednesday";
            case 2:
                return "Friday";
        }
        return null;
    }
}
}

I thought it would go in this part like so:

  switch (getArguments().getInt(ARG_SECTION_NUMBER)) {
            case 1:
                View rootView = inflater.inflate(R.layout.fragment_workout_days, container, false);

                Bundle extras = getArguments();
                CustomObject objects = (CustomObject) extras.getSerializable("w29w1");
                CustomListViewAdapter customListViewAdapter = new CustomListViewAdapter(this, objects);

But im getting an error under (this, objects) saying "cannot be applied to .placeholderfragment .custom object" "PlaceholderFragment cannot be converted to Context"

This is what I put in the onChildClick:

Bundle extras = new Bundle();
                    final ArrayList<CustomObject> objects = new ArrayList<CustomObject>();
                    objects.add(new CustomObject("Squat", "65%", "6", "150", false));
                    extras.putSerializable("w29w1", objects);

                    Intent intent = new Intent(getApplicationContext(), WorkoutDaysActivity.class);
                    intent.putExtra("args", extras);
                    startActivity(intent);

Thanks for the help! please let me know if you need to see any of my code to better understand what I'm trying to do!


Solution

  • I'm having some difficulty understanding the question completely, but here's my thoughts so far.

    Are you attempting to set the same instance of the list adapter on each list? If you want the same general behaviour, but to tie different data to a list, be sure you are instantiating new adapter instances for each list.

    i.e.

    myList1.setAdapter(new MyAdapter());
    myList2.setAdapter(new MyAdapter());
    

    rather than

    MyAdapter myAdapter = new MyAdapter();
    myList1.setAdapter(myAdapter);
    myList2.setAdapter(myAdapter);
    

    Additionally, it is wise to move data through intents when communicating with another activity. In your initial activity, when an action prompts launching the next activity, put the extras into the intent before calling startActivity(). Then, inside the next activity, you will call getIntent().getXXXExtra("...") where the XXX is type-matched to the extra you are extracting, and ... is the correct key you placed on the extra in the previous activity.

    If you are using fragments contained in activities, make use of Fragment.setArguments() (in activity2) and Fragment.getArguments() (in fragment2) to pass the extras from fragment1 to activity2 to fragment2.

    Passing Extras Around When you click an item and want to launch a new activity (a new view to display), a good approach is to bundle up the information needed, pass it to the new activity, unwrap all that information and then apply it to the views as you desire.

    For example...

    @Override
    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
    if (groupPosition == 0) {
        if (childPosition == 0) {
            Bundle extras = new Bundle();
            // Put all the extras you need. This can be primitives like int, boolean, double, or complex objects using the Serializable interface
            // For example, say your CustomObject implements Serializable
            CustomObject customObject = new CustomObject("Squats", "60%", "6", "150", false);
            extras.putSerializable("object_key_here", customObject);
    
            Intent intent = new Intent(getContext(), NextActivityHere.class);
            intent.putExtra("args", extras);
            startActivity(intent);
        }
    }
    

    In the activity containing the fragment which contains the list:

    // Likely in onCreate()
    Bundle extras = getIntent.getBundleExtra("args");
    MyFragment myFragment = new MyFragment();
    myFragment.setArguments(extras);
    // Use fragment manager to add the fragment to your view
    

    In the fragment (myFragment) containing the list:

    // Likely in onCreate()
    Bundle extras = getArguments();
    CustomObject customObject = (CustomObject) extras.getSerializable("object_key_here");
    
    // Now you can use the object to set up the adapter, etc...
    

    Hopefully this helps at least show how to get data from the original activity to the fragment containing the list. Usually I see myself passing an ArrayList of data if I'm going to be populating a list. Without knowing too much about your scenario, it's difficult to be more specific.