I'm trying to implement a FragmentPagerAdapter
with dynamically created Tabs based on a Cursor
that retrieves distinct values from an SQLite DB column.
Then the ListFragment
loads data based on a 2nd Cursor
that selects data with a filter based on the Tab name.
Finally I add a Tab to include "All" data, rather than a subset.
All is working well, except for getting the right data into the first "All" sheet. The ListFragment onCreateLoader
never gets to select "All" and somehow pulls data in both the first and second Tab, based on the second Tab's name.
My code (filtered for relevance; hopefully not too much)
MainActivity
public class MainActivity extends AppCompatActivity {
// arraylist of tabs in which tab details are stored
private ArrayList<String> tabNames;
// to hold tabs data when first fetch from sqlite db
private Cursor tabCursor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.simsolec.flavorsaver.R.layout.activity_main);
getTabs();
// Create an adapter that knows which fragment should be shown on each page
FlavorFragmentPagerAdapter adapter = new FlavorFragmentPagerAdapter(
getSupportFragmentManager(), MainActivity.this, tabNames);
// Find the view pager that will allow the user to swipe between fragments
ViewPager mViewPager = findViewById(com.simsolec.flavorsaver.R.id.viewpager);
// Set the adapter onto the view pager
mViewPager.setAdapter(adapter);
// Give the TabLayout the ViewPager
TabLayout tabLayout = findViewById(com.simsolec.flavorsaver.R.id.sliding_tabs);
tabLayout.setupWithViewPager(mViewPager);
}
private void getTabs( ){
try{
String[] Projection = { FlavorEntry.COLUMN_FLAVOR_RANGE };
tabCursor = getContentResolver().query(
FlavorEntry.CONTENT_URI_DISTINCT,
Projection,
null,
null,
FlavorEntry.COLUMN_FLAVOR_RANGE );
tabNames = new ArrayList();
tabNames.add("All");
if (tabCursor != null && tabCursor.getCount() > 0) {
if(tabCursor.moveToFirst()) {
do{
String tabName;
tabName = tabCursor.getString(0);
tabNames.add(tabName);
}while (tabCursor.moveToNext());
}
tabCursor.close();
}
}catch (NullPointerException | SQLException e) {
}
finally {
tabCursor.close();
}
}
}
FragmentPagerAdapter
public class FlavorFragmentPagerAdapter extends FragmentPagerAdapter {
private Context context;
private ArrayList<String> mTabNames;
public FlavorFragmentPagerAdapter(FragmentManager fm, Context context, ArrayList<String> tabNames) {
super(fm);
this.context = context;
mTabNames = tabNames;
}
@Override
public int getCount() {
//return PAGE_COUNT;
return mTabNames.size();
}
@Override
public Fragment getItem(int position) {
// return FlavorListFragment.newInstance(position + 1);
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
String tabName = mTabNames.get(position);
return FlavorListFragment.newInstance(tabName);
}
@Override
public CharSequence getPageTitle(int position) {
//Generate title based on item position
//return tabTitles[position];
String tabName = mTabNames.get(position);
return tabName;
}
}
ListFragment
public class FlavorListFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>{
// The fragment argument representing the tab name & number for this fragment.
private static final String ARG_TAB_NAME ="tabName";
// Store the tabName for later use
private static String mTabName;
public static FlavorListFragment newInstance(String tabName) {
FlavorListFragment fragment = new FlavorListFragment();
mTabName = tabName;
Bundle args = new Bundle();
args.putString(ARG_TAB_NAME, tabName);
fragment.setArguments(args);
return fragment;
}
/** Identifier for the flavor data loader */
private static final int FLAVOR_LOADER = 0;
/** Adapter for the ListView */
FlavorCursorAdapter mCursorAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(com.simsolec.flavorsaver.R.layout.fragment_flavor_list,
container, false);
// Find the ListView which will be populated with the flavor data
ListView flavorListView = rootView.findViewById(com.simsolec.flavorsaver.R.id.flavor_list);
// Setup an Adapter to create a list item for each row of flavor data in the Cursor.
// There is no flavor data yet (until the loader finishes) so pass in null for the Cursor.
mCursorAdapter = new FlavorCursorAdapter(getActivity(), null);
flavorListView.setAdapter(mCursorAdapter);
// Kick off the loader
getLoaderManager().initLoader(FLAVOR_LOADER, null, this);
// Setup the item click listener
flavorListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
// Create new intent to go to {@link FlavorActivity}
Intent intent = new Intent(getContext(), FlavorActivity.class);
// Form the content URI that represents the specific flavor that was clicked on,
// by appending the "id" (passed as input to this method) onto the
// {@link FlavorEntry#CONTENT_URI}.
// For example, the URI would be "content://com.simsolec.flavorsaver/flavors/2"
// if the flavor with ID 2 was clicked on.
Uri currentFlavorUri = ContentUris.withAppendedId(FlavorEntry.CONTENT_URI, id);
// Set the URI on the data field of the intent
intent.setData(currentFlavorUri);
// Launch the {@link FlavorActivity} to display the data for the current flavor.
startActivity(intent);
}
});
return rootView;
}
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
// Define a projection that specifies the columns from the table we care about.
String[] projection = {
FlavorEntry._ID,
FlavorEntry.COLUMN_FLAVOR_NAME,
FlavorEntry.COLUMN_DESCRIPTION_SHORT,
FlavorEntry.COLUMN_CUP_IMAGE,
FlavorEntry.COLUMN_RATING };
// This loader will execute the ContentProvider's query method on a background thread
String[] selectionArgs;
if (mTabName=="All") {
selectionArgs = new String[] {"*"};
} else {
selectionArgs = new String[] {mTabName};
}
String selection = FlavorEntry.COLUMN_FLAVOR_RANGE + " in (";
for (int s = 0; s < selectionArgs.length; s++) {
selection += "?, ";
}
selection = selection.substring(0, selection.length() - 2) + ")";
return new CursorLoader(getActivity(), // Parent activity context
FlavorEntry.CONTENT_URI, // Provider content URI to query
projection, // Columns to include in the resulting Cursor
selection, // No selection clause
selectionArgs, // No selection arguments
FlavorEntry.COLUMN_FLAVOR_NAME + " ASC"); // Default sort order
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Update {@link FlavorCursorAdapter} with this new cursor containing updated flavor data
mCursorAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// Callback called when the data needs to be deleted
mCursorAdapter.swapCursor(null);
}
}
Can someone point me in the right direction?
Thank you, -Joost
Set the value of mTabName
from Bundle not from newInstance()
method because mTabName is define as static so remove static keyword from mTabName
public static FlavorListFragment newInstance(String tabName) {
FlavorListFragment fragment = new FlavorListFragment();
// mTabName = tabName;
Bundle args = new Bundle();
args.putString(ARG_TAB_NAME, tabName);
fragment.setArguments(args);
return fragment;
}
OnCreateView of FlavorListFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(com.simsolec.flavorsaver.R.layout.fragment_flavor_list,
container, false);
Bundle b= getArguments();
//mTabName=b.getString(mTabName);
mTabName=b.getString(ARG_TAB_NAME);
}