Actually, i created a navigation drawer that has three items and on clicking on every item it goes to its fragment that displays certain type of products , so i have an Activity with three fragments for each type of them.
If i would like to add another product type i will have to create its fragment.
So ,My question is , are there any methods that can only make one fragment and every time an item is clicked only the data inside the fragment to be changed/replaced and not to replace the whole fragment itself with another ?
Edited my main activity:
public class MainActivity extends AppCompatActivity {
Toolbar toolbar;
DrawerLayout drawerLayout;
RecyclerView recyclerView;
String navTitles[];
private NavigationView navigationView;
TypedArray navIcons;
RecyclerViewAdapter recyclerViewAdapter;
ActionBarDrawerToggle drawerToggle;
Fragment[] fFragments = new Fragment[3];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Let's first set up toolbar
setupToolbar();
//Initialize Views
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
drawerLayout = (DrawerLayout) findViewById(R.id.drawerMainActivity);
//Setup Titles and Icons of Navigation Drawer
navTitles = getResources().getStringArray(R.array.navDrawerItems);
navIcons = getResources().obtainTypedArray(R.array.navDrawerIcons);
recyclerViewAdapter = new RecyclerViewAdapter(navTitles, navIcons, this);
recyclerView.setAdapter(recyclerViewAdapter);
recyclerViewAdapter.setClickedListener(new RecyclerViewAdapter.ClickListerner() {
#Override
public void onItemlistener(int index) {
updateUIWithIndex(index);
}
});
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//Finally setup ActionBarDrawerToggle
setupDrawerToggle();
//Add the Very First Fragment to the Container
updateUIWithIndex(1);
}
// on click update fragment
private void updateUIWithIndex(int index) {
drawerLayout.closeDrawers();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
Fragment fFragment = null;
if (fFragments[index - 1] == null) {
switch (index) {
case 1:
fFragment = new FirstFragment();
break;
case 2:
fFragment = new SecondFragment();
break;
case 3:
fFragment = new ThirdFragment();
break;
}
fFragments[index - 1] = fFragment;
} else {
fFragment = fFragments[index - 1];
}
fragmentTransaction.replace(R.id.containerView, fFragment);
fragmentTransaction.commit();
}
void setupToolbar() {
toolbar = (Toolbar) findViewById(R.id.toolBar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
void setupDrawerToggle() {
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.app_name, R.string.app_name);
//This is necessary to change the icon of the Drawer Toggle upon state change.
drawerToggle.syncState();
}
}
My Fragment :
public class FirstFragment extends Fragment implements ClickListner {
private final String LOG_TAG = FirstFragment.class.getSimpleName();
private DisplayAdapter recyclerViewAdapter;
private RecyclerView recyclView;
private ArrayList<Products> pProduct = null;
private List<Products> prods = null;
ProductDbHelper pDB;
ProgressDialog mJsonDialog;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View myView = inflater.inflate(R.layout.all_products, container, false);
pDB = new ProductDbHelper(getActivity());
mJsonDialog = new ProgressDialog(getActivity());
mJsonDialog.setIndeterminate(true);
if (pDB.isDataAvailable() == 0) {
mJsonDialog.setMessage("Parsing JSON feed...");
mJsonDialog.show();
getFeed();
} else {
new FetchDatabaseTask().execute();
}
return myView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclView = (RecyclerView) view.findViewById(R.id.RecycleList);
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
recyclView.setLayoutManager(layoutManager);
recyclerViewAdapter = new DisplayAdapter(getActivity(), new ArrayList<Products>());
recyclView.setAdapter(recyclerViewAdapter);
recyclerViewAdapter.setClickListener(this);
}
#Override
public void itemClicked(View view, Parcelable product) {
Intent intent = new Intent(getActivity(), DetailActivity.class);
intent.putExtra("P", product);
startActivity(intent);
}
public void getFeed() {
RestInterface interfaces = Client.getClient().create(RestInterface.class);
Call<List<Products>> call = interfaces.getProductsReport();
call.enqueue(new Callback<List<Products>>() {
#Override
public void onResponse(Call<List<Products>> call, Response<List<Products>> response) {
prods = response.body();
for (int i = 0; i < prods.size(); i++) {
pDB.addShop(prods.get(i));
}
new FetchDatabaseTask().execute();
if (mJsonDialog.isShowing())
mJsonDialog.dismiss();
}
#Override
public void onFailure(Call<List<Products>> call, Throwable t) {
Log.e(LOG_TAG, "FFFF" + t.toString());
}
});
}
public class FetchDatabaseTask extends AsyncTask<Void, Void, List<Products>> {
protected void onPreExecute() {
mJsonDialog.setMessage("Reading from internal storage...");
mJsonDialog.show();
}
#Override
protected List<Products> doInBackground(Void... voids) {
// get all the shop's products
List<Products> lProduct = pDB.getAllShops();
// in the second fragment , sort the products' price in ascending order
List<Products> lProduct = pDB.sortShopsAscend();
// in the third fragment sort the products descendingly
List<Products> lProduct = pDB.sortShopsDescend();
return lProduct;
}
protected void onPostExecute(List<Products> shops) {
super.onPostExecute(shops);
if (shops != null) {
if (recyclerViewAdapter != null) {
recyclerViewAdapter.setData(shops);
} else {
pProduct = new ArrayList<>();
pProduct.addAll(shops);
}
}
if (mJsonDialog.isShowing())
mJsonDialog.dismiss();
}
}
}
Make those changes in the MainActivity class :
public class MainActivity extends AppCompatActivity {
Toolbar toolbar;
DrawerLayout drawerLayout;
RecyclerView recyclerView;
String navTitles[];
private NavigationView navigationView;
TypedArray navIcons;
RecyclerViewAdapter recyclerViewAdapter;
ActionBarDrawerToggle drawerToggle;<
//If you want to use the first fragment only
FirstFragment fragment = null;
.
.
.
recyclerViewAdapter.setClickedListener(new RecyclerViewAdapter.ClickListerner() {
#Override
public void onItemlistener(int index) {
//Call this method to close the drawer layout or you can simply call the close method here
updateUIWithIndex(index);
//Do something depending on the index
if(index == 0){
//Call getFeed() for example
fragment.getFeed();
}
else if(index == 1){
//call another method
}
}
});
.
.
.
// on click update fragment
//I don't know if you still need the index in this method
private void updateUIWithIndex(int index) {
//Close the drawer Layout anyway
drawerLayout.closeDrawers();
if (fragment == null) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
//Create an instance of the FirstFragment
fragment = new FirstFragment();
fragmentTransaction.replace(R.id.containerView, fragment);
fragmentTransaction.commit();
}
}
You can simply pass variable to Fragment method.
Completely updated post
In your case:
set fragment as field in your MainActivity
private FirstFragment firstFragment;
Run this fragment in your OnCreate method in MainActivity
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
firstFragment = null;
firstFragment = new FirstFragment();
fragmentTransaction.replace(R.id.containerView, firstFragment );
fragmentTransaction.commit();
Then replace updateUIWithIndex method to fragment method, so you have:
recyclerViewAdapter.setClickedListener(new RecyclerViewAdapter.ClickListerner() {
#Override
public void onItemlistener(int index) {
firstFragment.getFeed(index)
}
});
Pass index to getFeed:
public void getFeed(int index) {
final int currentIndex = index;
RestInterface interfaces = Client.getClient().create(RestInterface.class);
Call<List<Products>> call = interfaces.getProductsReport();
call.enqueue(new Callback<List<Products>>() {
#Override
public void onResponse(Call<List<Products>> call, Response<List<Products>> response) {
prods = response.body();
for (int i = 0; i < prods.size(); i++) {
pDB.addShop(prods.get(i));
}
new FetchDatabaseTask(currentIndex ).execute();
if (mJsonDialog.isShowing())
mJsonDialog.dismiss();
}
#Override
public void onFailure(Call<List<Products>> call, Throwable t) {
Log.e(LOG_TAG, "FFFF" + t.toString());
}
});
Add constructor to FetchDatabaseTask class
public class FetchDatabaseTask extends AsyncTask<Void, Void, List<Products>> {
private int currentIndex = 0;
FetchDatabaseTask(int index) {
currentIndex = index;
}
//ur others methods here
}
And then you can do as you need in onPreExecute,doInBackground and onPostExecute methods like this:
protected void onPostExecute(List<Products> shops) {
super.onPostExecute(shops);
switch (currentIndex) {
case 0:
if (shops != null) {
if (recyclerViewAdapter != null) {
recyclerViewAdapter.setData(shops);
} else {
pProduct = new ArrayList<>();
pProduct.addAll(shops);
}
}
if (mJsonDialog.isShowing())
mJsonDialog.dismiss();
break;
case 1:
//ur SecondFragment code
break;
case 2:
//ur ThirdFragment code
break;
}
}
So you can use only one fragment for every type of product or whatever you want.
Related
In my App, I have two Fragments: FragmentA and FragmentB which are loaded from my MainActivity by the help of an SlidingMenu.
Thanks to Crashlytics I get notified when and where my app crashes. In this case, from time to time the DatabaseHandler in FragmentA is null (for some users), even though it has been initzialized.
This is my Code:
MainActivity
public class MainActivity extends AppCompatActivity implements MyFragment.OnListFragmentInteractionListener, AsyncResponse {
private FragmentA fragmentA = new FragmentA();
private DatabaseHandler databaseHandler = new DatabaseHandler(this);
private NavigationView navigationView;
private DrawerLayout drawer;
private Toolbar toolbar;
// index to identify current nav menu item
private static int navItemIndex = 0;
public static String CURRENT_TAG = MyConstants.TAG_FRAGMENT_A;
// toolbar titles respected to selected nav menu item
private String[] activityTitles;
// flag to load home fragment when user presses back key
private Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentA.setDatabaseHandler(this.databaseHandler);
// Init UI
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mHandler = new Handler();
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
navigationView = (NavigationView) findViewById(R.id.nav_view);
fabSendButton = (FloatingActionButton) findViewById(R.id.fab);
// Navigation view header
navHeader = navigationView.getHeaderView(0);
// load toolbar titles from string resources
activityTitles = getResources().getStringArray(R.array.sliding_menu_item_activity_titles);
// initializing navigation menu
setUpNavigationView();
if (savedInstanceState == null) {
navItemIndex = 0;
CURRENT_TAG = MyConstants.TAG_FRAGMENT_A;
loadHomeFragment();
}
}
/***
* Returns respected fragment that user
* selected from navigation menu
*/
private void loadHomeFragment() {
// set toolbar title
setToolbarTitle();
// if user select the current navigation menu again, don't do anything
// just close the navigation drawer
if (getSupportFragmentManager().findFragmentByTag(CURRENT_TAG) != null) {
drawer.closeDrawers();
return;
}
// Sometimes, when fragment has huge data, screen seems hanging
// when switching between navigation menus
// So using runnable, the fragment is loaded with cross fade effect
// This effect can be seen in GMail app
Runnable mPendingRunnable = new Runnable() {
#Override
public void run() {
// update the activity_main_header_with_item content by replacing fragments
Fragment fragment = getFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
fragmentTransaction.replace(R.id.frame, fragment, CURRENT_TAG);
fragmentTransaction.commit();
}
};
// If mPendingRunnable is not null, then add to the message queue
if (mPendingRunnable != null) {
mHandler.post(mPendingRunnable);
}
//Closing drawer on item click
drawer.closeDrawers();
// refresh toolbar menu
invalidateOptionsMenu();
}
private Fragment getFragment() {
switch (navItemIndex) {
case 0:
return this.fragmentA;
case 1:
Fragment B fragmentB = new FragmentB();
fragmentB.setDatabaseHandler(this.databaseHandler);
return fragmentB;
default:
return this.fragmentA;
}
}
private void setToolbarTitle() {
getSupportActionBar().setTitle(activityTitles[navItemIndex]);
}
private void setUpNavigationView() {
//Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Check to see which item was being clicked and perform appropriate action
switch (menuItem.getItemId()) {
//Replacing the activity_main_header_with_item content with ContentFragment Which is our Inbox View;
case R.id.nav_A:
navItemIndex = 0;
CURRENT_TAG = MyConstants.TAG_FRAGMENT_A;
break;
case R.id.nav_B:
navItemIndex = 1;
CURRENT_TAG = MyConstants.TAG_FRAGMENT_B;
break;
default:
navItemIndex = 0;
}
loadHomeFragment();
return true;
}
});
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.openDrawer, R.string.closeDrawer) {
#Override
public void onDrawerClosed(View drawerView) {
// Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
// Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank
super.onDrawerOpened(drawerView);
}
};
//Setting the actionbarToggle to drawer layout
drawer.setDrawerListener(actionBarDrawerToggle);
//calling sync state is necessary or else your hamburger icon wont show up
actionBarDrawerToggle.syncState();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main_header_with_item, menu);
return true;
}
}
FragmentA:
public class FragmentA extends MyFragment implements AsyncResponse {
private View view;
private RecyclerView recyclerView;
public FragmentA() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
List<Song> songsList = databaseHandler.getAllSongs();
view = inflater.inflate(R.layout.home_list, container, false);
// Set the adapter
Context context = view.getContext();
recyclerView = (RecyclerView) view.findViewById(R.id.listinclude);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), R.drawable.divider));
setVisibilities(songsList);
this.recyclerViewAdapter = new RecyclerViewAdapter(songsList, mListener, false, true);
recyclerView.setAdapter(this.recyclerViewAdapter);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
private void setVisibilities(List<Song> songsList) {
ViewFlipper viewFlipper = (ViewFlipper) view.findViewById(R.id.viewFlipper);
if (songsList.isEmpty() && viewFlipper.getDisplayedChild() == 0) {
viewFlipper.setDisplayedChild(1);
} else if (!songsList.isEmpty() && viewFlipper.getDisplayedChild() == 1) {
viewFlipper.setDisplayedChild(0);
}
}
#Override
public void processFinish(String output) {
// does something
}
}
MyFragment
public class MyFragment extends Fragment {
protected DatabaseHandler databaseHandler;
protected static final String ARG_COLUMN_COUNT = "column-count";
protected int mColumnCount = 1;
protected MyFragment.OnListFragmentInteractionListener mListener;
protected RecyclerViewAdapter recyclerViewAdapter;
public void setDatabaseHandler(DatabaseHandler databaseHandler) {
this.databaseHandler = databaseHandler;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Timber.i( "onCreate");
if (getArguments() != null) {
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
}
}
#Override
public void onPause() {
Timber.i( "onPause");
super.onPause();
}
#Override
public void onAttach(Context context) {
Timber.i( "onAttach");
super.onAttach(context);
if (context instanceof OnListFragmentInteractionListener) {
mListener = (FragmentA.OnListFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString() + " must implement OnListFragmentInteractionListener");
}
}
#Override
public void onDetach() {
Timber.i( "onDetach");
super.onDetach();
mListener = null;
}
public interface OnListFragmentInteractionListener {
// TODO: Update argument type and name
void onListFragmentInteraction(Song item);
}
}
DatabaseHandler:
public class DatabaseHandler extends SQLiteOpenHelper {
// All Static variables
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "appName";
// Songs table name
private static final String TABLE_SONGS = "songs";
#Override
public void onCreate(SQLiteDatabase db) {
// create Tables
}
// Upgrading database
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch(oldVersion) {
case 1:
//upgrade logic from version 1 to 2
case 2:
//upgrade logic from version 2 to 3
case 3:
//upgrade logic from version 3 to 4
break;
default:
throw new IllegalStateException(
"onUpgrade() with unknown oldVersion " + oldVersion);
}
}
// Getting All Songs
public List<Song> getAllSongs() {
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_SONGS + " ORDER BY ID DESC";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
List<Song> songList = new ArrayList<>();
songList.addAll(getSongsFromCursor(cursor));
cursor.close();
// return title list
return songList;
}
}
Problem:
Fatal Exception: java.lang.RuntimeException
Unable to start activity ComponentInfo{com.myapp.myappname/com.myapp.myappname.ui.activity.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.myapp.myappname.database.DatabaseHandler.getAllSongs()' on a null object reference
Details:
Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myapp.myappname/com.myapp.myappname.ui.activity.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.myapp.myappname.database.DatabaseHandler.getAllSongs()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2984)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.myapp.myappname.database.DatabaseHandler.getAllSongs()' on a null object reference
at com.myapp.myappname.ui.fragment.FragmentA.onCreateView(FragmentA.java:51)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2192)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1299)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:2900)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:603)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
at com.myapp.myappname.ui.activity.MainActivity.onStart(MainActivity.java:590)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1256)
at android.app.Activity.performStart(Activity.java:6972)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2937)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
try this one
databaseHandler=new DataBaseHandler(getActivity());
List<Song> songsList = databaseHandler.getAllSongs();
And add constructor in the DataBaseHandler class
public DataBaseHandler(Context context){
super(context, DB_NAME, null, 1);
}
try this on FragmentA.
databaseHandler=new DataBaseHandler(getContext());
you are taking context of mainActivity to initialize databaseHandler but using in fragment.
Found a solution based on Serg's answer:
FragmentA:
public class FragmentA extends MyFragment implements AsyncResponse {
private View view;
private RecyclerView recyclerView;
public FragmentA() {
}
public static FragmentA newInstance(DatabaseHandler DatabaseHandler) {
FragmentA fragment = new FragmentA();
Bundle bundle = new Bundle();
bundle.putSerializable(MyConstants.FRAGMENT_ARGUMENT_KEY, databaseHandler);
fragment.setArguments(bundle);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
databaseHandler = (DatabaseHandler) getArguments().getSerializable(MyConstants.FRAGMENT_ARGUMENT_KEY);
List<Song> songsList = databaseHandler.getAllSongs();
view = inflater.inflate(R.layout.home_list, container, false);
// Set the adapter
Context context = view.getContext();
recyclerView = (RecyclerView) view.findViewById(R.id.listinclude);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), R.drawable.divider));
setVisibilities(songsList);
this.recyclerViewAdapter = new RecyclerViewAdapter(songsList, mListener, false, true);
recyclerView.setAdapter(this.recyclerViewAdapter);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
private void setVisibilities(List<Song> songsList) {
ViewFlipper viewFlipper = (ViewFlipper) view.findViewById(R.id.viewFlipper);
if (songsList.isEmpty() && viewFlipper.getDisplayedChild() == 0) {
viewFlipper.setDisplayedChild(1);
} else if (!songsList.isEmpty() && viewFlipper.getDisplayedChild() == 1) {
viewFlipper.setDisplayedChild(0);
}
}
#Override
public void processFinish(String output) {
// does something
}
}
MainActivity:
fragmentA = FragmentA.newInstance(this.databaseHandler);
I have a TabLayout with 4 tabs in my Activity and I have made a Fragment per each Tab.
Below is my Activity code:
public class MyActivity extends AppCompatActivity {
private static final String TAG = "RecyclerView";
private Toolbar toolbar;
private static ViewPager viewPager;
private static TabLayout tabLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Allow activity to show indeterminate progressbar */
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.student_regulations_list);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewPager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(onTabSelectedListener(viewPager));
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment1(), getString(R.string.titleA));
adapter.addFragment(new Fragment2(), getString(R.string.titleB));
adapter.addFragment(new Fragment3(), getString(R.string.titleC));
adapter.addFragment(new Fragment4(), getString(R.string.titleD));
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(3);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
}
private TabLayout.OnTabSelectedListener onTabSelectedListener(final ViewPager viewPager) {
return new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());//setting current selected item over viewpager
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
};
}
//View Pager fragments setting adapter class
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();//fragment arraylist
private final List<String> mFragmentTitleList = new ArrayList<>();//title arraylist
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
//adding fragments and title method
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
I have a RecyclerView in each fragment, and I fetch data from a Web Service using AsyncTask to show in the RecyclerView. Each item in RecyclerView has an ID and I want to When I switch between tabs and click on an item in RecyclerView, a Toast shows it's ID.
Below is a Fragment code:
public class Fragment1 extends Fragment implements ClickListener {
private static final String TAG = "RecyclerView";
private List<FeedItem> feedItemList;
private RecyclerView mRecyclerView;
private FeedsRecyclerAdapter mAdapter;
final String url = "a valid url";
private View rootView;
private ProgressBar progressBar;
public StuRegGeneralListFragment() {
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_student_regulations_list, container, false);
return rootView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
progressBar = (ProgressBar) rootView.findViewById(R.id.progress_bar);
/* Initialize recyclerview */
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
/*Downloading data from below url*/
new AsyncHttpTask().execute(url);
}
#Override
public void itemClicked(View view, int position) {
FeedItem item = feedItemList.get(position);
Intent intent = new Intent(getActivity(), JsonRequestFeedActivity.class);
intent.putExtra("url", Const.URL_JSON_OBJECT_REGS + item.getID());
intent.putExtra("pid", item.getID());
//startActivity(intent);
Toast.makeText(getActivity(), "Item ID: " + item.getID(), Toast.LENGTH_SHORT).show();
}
public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {
#Override
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
feedItemList = new ArrayList<FeedItem>();
}
#Override
protected Integer doInBackground(String... params) {
InputStream inputStream = null;
Integer result = 0;
HttpURLConnection urlConnection = null;
try {
/* forming th java.net.URL object */
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
/* for Get request */
urlConnection.setRequestMethod("GET");
int statusCode = urlConnection.getResponseCode();
/* 200 represents HTTP OK */
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
parseResult(response.toString());
result = 1; // Successful
} else {
result = 0; //"Failed to fetch data!";
}
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
return result; //"Failed to fetch data!";
}
#Override
protected void onPostExecute(Integer result) {
progressBar.setVisibility(View.GONE);
/* Download complete. Lets update UI */
if (result == 1) {
updateRecyclerView();
} else {
Log.e(TAG, "Failed to fetch data!");
}
}
}
private void parseResult(String result) {
try {
JSONObject response = new JSONObject(result);
JSONArray posts = response.optJSONArray("posts");
/*Initialize array if null*/
if (null == feedItemList) {
feedItemList = new ArrayList<FeedItem>();
}
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
FeedItem item = new FeedItem();
item.setID(post.optString("id"));
item.setDate(post.optString("date"));
item.setTitle(post.optString("title"));
item.setThumbnail(post.optString("thumbnail"));
feedItemList.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public void updateRecyclerView() {
mAdapter = new FeedsRecyclerAdapter(getActivity(), feedItemList);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setClickListener(this);
}
}
Assuming each fragment has 5 items in RecyclerView (from ID 1 to 5 in fragment1, from ID 6 to 10 in fragment2, ...) I expect when I enter to my Activity and click on an item in fragment1 (for example first item), ID=1 be shown in Toast, but ID=16 is shown!
In fact because of viewPager.setOffscreenPageLimit(3); in my Activity, fragment1 and fagment2 and fragment3 and fragment4 are created and at the end, mAdapter contains item IDs 16-20, although I am in fragment1.
I expect after creating specified fragments by viewPager.setOffscreenPageLimit(int); each fragment has it's own adapter, but it's not happened.
Any help is appreciated.
I found out my mistake!
My Activity and Fragments code are correct, my mistake was in ClickListener of RecyclerView. It's implementation was not suitable in my case.
I had used a static clickListener in it, that was the point!
I have one activity, fragment with listView and fragment with details for each listView item. I am getting fragments data from API. How should I save loaded date and listView position correctly to be able to restore it when I am returning back to the listView?
I tried to implement this solution Once for all, how to correctly save instance state of Fragments in back stack? but I cannot restore my listView correctly.
My MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Set the fragment initially
listFragment = new ListFragment();
fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, listFragment);
fragmentTransaction.commit();
if (savedInstanceState != null) {
//Restore the fragment's instance
listFragment = (ListFragment)getSupportFragmentManager().getFragment(savedInstanceState, "listContent");
}
...
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Save the fragment's instance
getSupportFragmentManager().putFragment(outState, "listContent", listFragment);
}
and ListFragment
public class ListFragment extends Fragment {
public static final String REQUEST_TAG = "ProjectListFragment";
private int page;
private View view;
private RelativeLayout loading ;
private PagingListView listView;
private PagingProjectListAdapter adapter;
private ArrayList<String> projects = new ArrayList<>();
private ArrayList<String> loadedProjects = new ArrayList<>();
public ListFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_list, container, false);
listView = (PagingListView) view.findViewById(R.id.projectsListView);
loading = (RelativeLayout) view.findViewById(R.id.loading);
//page = 1;
adapter = new PagingProjectListAdapter(getContext(), ListFragment.this);
listView.setAdapter(adapter);
listView.setHasMoreItems(true);
// Inflate the layout for this fragment
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
// FIXME not used
listView.onFinishLoading(true, projects);
//Restore the fragment's state here
} else {
projects.clear();
page = 1;
listView.setPagingableListener(new PagingListView.Pagingable() {
#Override
public void onLoadMoreItems() {
new CustomVolleyAsyncTask().execute();
}
});
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("currentPosition", 0);
//Save the fragment's state here
}
public void itemClickMethod(View detailsView) {
LinearLayout linearLayout = (LinearLayout) detailsView;
String bid = linearLayout.getContentDescription().toString();
Bundle bundle = new Bundle();
String k = "ProjectID";
bundle.putString(k, bid);
DetailsFragment detailsFragment = new DetailsFragment();
detailsFragment.setArguments(bundle);
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, detailsFragment, "DetailsFragmentTag");
ft.addToBackStack(null);
ft.commit();
}
private class CustomVolleyAsyncTask extends SafeAsyncTask<List<String>> implements Response.Listener,
Response.ErrorListener {
public List<String> status = null;
private RequestQueue mQueue;
#Override
public List<String> call() throws Exception {
mQueue = CustomVolleyRequestQueue.getInstance(view.getContext())
.getRequestQueue();
String url = "http://www.myapi.com/api/v1/data/" + Integer.toString(page);
final CustomJSONObjectRequest jsonRequest = new CustomJSONObjectRequest(Request.Method
.GET, url,
new JSONObject(), this, this);
jsonRequest.setTag(REQUEST_TAG);
mQueue.add(jsonRequest);
// TODO rm redundant result
return status;
}
#Override
public void onErrorResponse(VolleyError error) {
// FIXME check no response case crash
//mTextView.setText(error.getMessage());
}
#Override
public void onResponse(Object response) {
try {
JSONArray projectsJSON = new JSONArray(((JSONObject) response).getString("projects"));
loadedProjects.clear();
for (int i=0; i < projectsJSON.length(); i++) {
loadedProjects.add(projectsJSON.getJSONObject(i).toString());
}
page++;
listView.onFinishLoading(true, loadedProjects);
if (loading.getVisibility() == View.VISIBLE && !listView.isLoading()){
listView.setVisibility(View.VISIBLE);
loading.setVisibility(View.GONE);
}
} catch (JSONException e) {
e.printStackTrace();
}}}
}
currently, my savedInstanceState is always null, what am I missing?
I think, that your fragment created twice, when configuration changed. Here Staffan explain, why this happend. I resolve similar problem by this way (in activity onCreate):
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(TAG);
if(fragment==null)
fragmentManager.beginTransaction()
.add(R.id.container, NewsFragment.newInstance(),TAG)
.commit();
I have a MainActivity which has AppBar containing toolbar and TabLayout, and also ViewPager.
MainActivity holds 4 fragments home, cash, card and account.
public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
private ViewPager viewPager;
private AppBarLayout appBarLayout;
Window window;
#Override
#SuppressWarnings("deprecation")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
window = this.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setStatusBarColor(this.getResources().getColor(R.color.color_primary_green_dark));
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar ab = getSupportActionBar();
ab.setTitle("Example Wallet");
toolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
appBarLayout = (AppBarLayout) findViewById(R.id.appBarLayout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
Toast.makeText(getBaseContext(), "Tab " + position + " Onpage Selected " + viewPager.getCurrentItem(), Toast.LENGTH_SHORT).show();
if (position == 0) {
appBarLayout.setBackgroundColor(getResources().getColor(R.color.color_primary_green));
tabLayout.setBackgroundColor(getResources().getColor(R.color.color_primary_green_dark));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setStatusBarColor(getResources().getColor(R.color.color_primary_green_dark));
}
} else if (position == 1) {
appBarLayout.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
tabLayout.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));
}
} else if (position == 2) {
appBarLayout.setBackgroundColor(getResources().getColor(R.color.color_primary_yellow));
tabLayout.setBackgroundColor(getResources().getColor(R.color.color_primary_yellow_dark));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setStatusBarColor(getResources().getColor(R.color.color_primary_yellow_dark));
}
} else if (position == 3) {
appBarLayout.setBackgroundColor(getResources().getColor(R.color.color_primary_red));
tabLayout.setBackgroundColor(getResources().getColor(R.color.color_primary_red_dark));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setStatusBarColor(getResources().getColor(R.color.color_primary_red_dark));
}
} else {
appBarLayout.setBackgroundColor(getResources().getColor(R.color.color_primary_green));
tabLayout.setBackgroundColor(getResources().getColor(R.color.color_primary_green_dark));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.setStatusBarColor(getResources().getColor(R.color.color_primary_green_dark));
}
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
FloatingActionButton fab1 = (FloatingActionButton) findViewById(R.id.fab);
if (fab1 != null) {
fab1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent registerIntent = new Intent(MainActivity.this, Detail.class);
startActivity(registerIntent);
}
});
}
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new FragmentMain(), "Home");
adapter.addFrag(new FragmentCash(), "Cash");
adapter.addFrag(new FragmentCard(), "Card");
adapter.addFrag(new FragmentAccount(), "Account");
adapter.addFrag(PartThreeFragment.createInstance(20), "Tab1");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
// return null to display only the icon
return mFragmentTitleList.get(position);
}
}
}
home fragment code
public class FragmentMain extends Fragment {
private List<Movie> movieList1 = new ArrayList<>();
private List<Movie> movieList2 = new ArrayList<>();
private RecyclerView recyclerView,recyclerView1;
private MovieAdapter mAdapter1,mAdapter2;
private LinearLayout cash_layout,card_layout,account_layout;
private ViewGroup c;
public FragmentMain() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v= inflater.inflate(R.layout.content_main, container, false);
//final android.app.ActionBar actionBar = getActivity().getActionBar();
//c=container;
recyclerView = (RecyclerView) v.findViewById(R.id.my_recycler_view);
cash_layout = (LinearLayout) v.findViewById(R.id.linearLayout_cash_bal);
card_layout = (LinearLayout) v.findViewById(R.id.linearLayout_card_bal);
account_layout = (LinearLayout) v.findViewById(R.id.linearLayout_account_bal);
mAdapter1 = new MovieAdapter(movieList1);
RecyclerView.LayoutManager mLayoutManager1 = new LinearLayoutManager(v.getContext());
recyclerView.setLayoutManager(mLayoutManager1);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter1);
prepareMovieData1();
cash_layout.setOnClickListener(new View.OnClickListener() {
#Override
#SuppressWarnings("deprecation")
public void onClick(View v) {
getContext().getActionBar().setSelectedNavigationItem(2);
/*actionBar.selectTab(actionBar.getTabAt(1));
FragmentManager fm=getFragmentManager();
fm.beginTransaction().replace(R.layout.content_cash, (Fragment)new FragmentCash()).commit();
getActivity().getActionBar().setTitle("Home");
//ActionBar actionBar = getActivity().getActionBar();*/
/*FragmentCash fragment2 = new FragmentCash();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container,fragment2);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();*/
}
});
/*mAdapter2 = new MovieAdapter(movieList2);
RecyclerView.LayoutManager mLayoutManager2 = new LinearLayoutManager(v.getContext());
recyclerView1.setLayoutManager(mLayoutManager2);
recyclerView1.setItemAnimator(new DefaultItemAnimator());
recyclerView1.setAdapter(mAdapter2);
prepareMovieData2();*/
return v;
}
private void prepareMovieData1() {
movieList1.clear();
Movie movie = new Movie("info","List is empty", "To create an item, click on (+) button", "","");
movieList1.add(movie);
mAdapter1.notifyDataSetChanged();
}
/*public void onClick1(View v) {
FragmentCash fragment2 = new FragmentCash();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(android.R.id.content,fragment2);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}*/
/*private void prepareMovieData2() {
Movie movie = new Movie("card","Card", "New Dress", "Rs.50.00","11/09/2016");
movieList2.add(movie);
mAdapter2.notifyDataSetChanged();
}*/
}
I am trying to call cash, card and account fragment from home fragment but this code
cash_layout.setOnClickListener(new View.OnClickListener() {
#Override
#SuppressWarnings("deprecation")
public void onClick(View v) {
FragmentCash fragment2 = new FragmentCash();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container,fragment2);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
adds other fragment with home fragment visible.
The solution I need is, in the below image when I click the cash balance it slide to the cash tab with cash fragment onscreen.
It looks like you are trying to add the cash fragment on top of the view pager, or replace it all together. Instead of replacing it in the current view, I'm assuming you would like to navigate to it within the viewPager.
To do that, replace all of your onClick code with pager.setCurrentItem(//Page number with cash fragment on it)
So, your onClick would look something like this:
cash_layout.setOnClickListener(new View.OnClickListener() {
#Override
#SuppressWarnings("deprecation")
public void onClick(View v) {
((MainActivity) getActivity()).getViewPager().setCurrentItem(//Your desired page number as int);
}
});
Or you could solve this easily with an interface.
Just create an interface to access your viewPager's operations like so.
public interface ViewPagerInterface {
ViewPager getViewPager();
}
Have your activity implement it:
public MainActivity extends AppCompatActvity implements ViewPagerInterface {
#Override
public ViewPager getViewPager() {
return this.viewPager;
}
}
Then pass that interface to your Fragments and call the getViewPager method.
viewPagerInterface.getViewPager().setCurrentItem(<my-int>);
I want to create soemthing like this:
The ViewPager is attached to an adapter which has 2 fragments. One to list the upcoming orders and the other to list the past orders.
So the image shown above has a main fragment which hosts the ViewPager, and the adapter creates 2 fragments as children of the main fragment.
For sake of simplicity I'll call the main fragment as "Parent fragment" and the two fragments supplied by the adapter as "children fragments".
Once the parent fragment is created or resumed it has to fetch a list of data from the server and pass it to the two children fragment(The children fragments will process the list of data and display the necessary data). Both the children fragments have a listView, and each listView row item is clickable.
Now, the data fetched by the parent fragment has to be passed to the children fragments before the ViewPager is attached to the adapter. So I do not attach the adapter to the ViewPager in the onCreate method of the parent fragment, but rather once the list of data is fetched, I attach the adapter to the ViewPager in the onPostExecute method of the async task after the data is fetched.
This works fine the first time, but once I click on a listView row item of the child fragment and then press the back button, the getItem() method of the adapter is not called, but the onResume methods of the children fragments are called even before the data is fetched from the server.
So I guess the android framework remembers that the children fragment have already been created, and does not recreate them again.
How do I ensure that the children fragments are created/called only after the data is fetched from the server in the parent fragment?
I am adding some code for clarity.
BookingHistory.java(Parent Fragment)
public class BookingHistory extends android.support.v4.app.Fragment {
ViewPager mPager;
SlidingTabLayout mTabs;
Toolbar toolBar;
View view;
private ProgressDialog progress;
private OrderTask mOrderTask = null;
UserFunctions userFunctions = null;
OrderFunctions orderFunctions = null;
private BookingHistoryListener mListener;
private List<Order> mOrderList;
PlacedOrders upcomingOrders;
PlacedOrders pastOrders;
public BookingHistory() {
// Required empty public constructor
}
#Override
public void onResume() {
super.onResume();
mOrderList = null;
mPager = null;
mTabs = null;
upcomingOrders = null;
pastOrders = null;
progress = new ProgressDialog(getActivity());
fetchOrders();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_booking_history, container, false);
toolBar = (Toolbar) view.findViewById(R.id.toolbar_s);
if (toolBar != null) {
TextView tv = (TextView) view.findViewById(R.id.toolbar_title);
toolBar.setTitle("");
tv.setText("History");
}
return view;
}
class MyPagerAdapter extends FragmentPagerAdapter {
String tabs[] = {"Upcoming", "Past"};
public MyPagerAdapter(android.support.v4.app.FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
if (position == 0) {
upcomingOrders = PlacedOrders.newInstance(Constants.DATE_TODAY_FUTURE);
upcomingOrders.getOrderList(mOrderList);
return upcomingOrders;
} else {
pastOrders = PlacedOrders.newInstance(Constants.DATE_PAST);
pastOrders.getOrderList(mOrderList);
return pastOrders;
}
}
#Override
public CharSequence getPageTitle(int position) {
return tabs[position];
}
#Override
public int getCount() {
return 2;
}
}
public void fetchOrders() {
if (mOrderTask != null) {
return;
}
progress.show();
mOrderTask = new OrderTask(getActivity());
mOrderTask.execute((Void) null);
}
public class OrderTask extends AsyncTask<Void, Void, Boolean> {
private final Activity mActivity;
OrderTask(Activity activity) {
mActivity = activity;
}
#Override
protected Boolean doInBackground(Void... params) {
userFunctions = new UserFunctions();
orderFunctions = new OrderFunctions();
return orderFunctions.getList(userFunctions.getToken(mActivity));
}
#Override
protected void onPostExecute(final Boolean success) {
mOrderTask = null;
progress.dismiss();
if (success) {
mOrderList = UserProfile.getOrders();
//attaching the view pager to adapter here!
mPager = (ViewPager) view.findViewById(R.id.pager);
mTabs = (SlidingTabLayout) view.findViewById(R.id.sliding_tabs);
mTabs.setDistributeEvenly(true);
mTabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.white);
}
});
mPager.setAdapter(new MyPagerAdapter(getChildFragmentManager()));
mTabs.setViewPager(mPager);
} else {
//Error handling stuff
}
}
}
}
PlacedOrders.java(Children Fragments)
public class PlacedOrders extends android.support.v4.app.Fragment {
private static String flag;
private int dateFlag;
private PlacedOrdersListener mListener;
UserFunctions userFunctions = null;
OrderFunctions orderFunctions = null;
private PlacedOrdersAdapter ordersAdapter;
private ProgressDialog progress;
private List<Order> mOrderList;
private List<Order> mPendingOrderList;
private List<Order> mCompletedOrderList;
public static PlacedOrders newInstance(int date) {
PlacedOrders fragment = new PlacedOrders();
Bundle args = new Bundle();
args.putInt(flag, date);
fragment.setArguments(args);
return fragment;
}
public void getOrderList(List<Order> orderList) {
this.mOrderList = orderList;
}
public PlacedOrders() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
dateFlag = getArguments().getInt(flag);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mPendingOrderList = new ArrayList<Order>();
mCompletedOrderList = new ArrayList<Order>();
return inflater.inflate(R.layout.fragment_placed_orders, container, false);
}
#Override
public void onResume() {
super.onResume();
displayOrders();
}
private void displayOrders() {
if (isVisible() && (mOrderList != null)) {
mPendingOrderList.clear();
mCompletedOrderList.clear();
ListView listViewOrder = (ListView) getView().findViewById(R.id.orderList);
if(dateFlag == Constants.DATE_TODAY_FUTURE) {
for(int i = 0; i < mOrderList.size(); i++) {
String status = mOrderList.get(i).status;
if(status.equals("PENDING") || status.equals("PROCESSING")) {
mPendingOrderList.add(mOrderList.get(i));
ordersAdapter = new PlacedOrdersAdapter(mPendingOrderList, getActivity().getLayoutInflater());
listViewOrder.setAdapter(ordersAdapter);
}
}
}
else if(dateFlag == Constants.DATE_PAST) {
for(int i = 0; i < mOrderList.size(); i++) {
String status = mOrderList.get(i).status;
if(status.equals("COMPLETE")) {
mCompletedOrderList.add(mOrderList.get(i));
ordersAdapter = new PlacedOrdersAdapter(mCompletedOrderList, getActivity().getLayoutInflater());
listViewOrder.setAdapter(ordersAdapter);
}
}
}
listViewOrder.setOnItemClickListener(new AdapterView.OnItemClickListener() {
//Display a new fragment on clicking
});
}
}
}
I had same issue and this was my solution :
In container fragment (fragment that contains tabs) in onViewCreated() method I created startFetch() method:
#Override
public void onViewCreated(View v, Bundle savedInstanceState) {
super.onViewCreated(v, savedInstanceState);
mViewPager = (ViewPager) v.findViewById(R.id.home_tab_pager);
mTabsHost= (TabLayout) getActivity().findViewById(R.id.appTabs);
startFetch();
}
Then in startFetch method i use Volley request and in onResponse method i update data and then add tabs :
public void startFetch(){
//Create volley request
String url = BuildConfig.API_GET_CATEGORIES;
final RequestQueue queue = VolleyService.getInstance(this.getContext()).getRequestQueue();
StringRequest request = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// we got the response, now our job is to handle it
try {
updateCategoryData(response);
} catch (RemoteException | OperationApplicationException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//something happened, treat the error.
Log.e("ErrorFETCH", error.networkResponse.toString());
}
});
queue.add(request);
}
My udpateCategory() method :
public void updateCategoryData(final String stream) throws RemoteException, OperationApplicationException {
//Update the data to SQLITE
setupTabs();
}
My setupTabs() method :
public void setUpTabs(){
ArrayList<Category> categories = new ArrayList<>();
Cursor data = getActivity().getContentResolver().query(
Category.Entry.CONTENT_URI, // URI
Category.PROJECTION, // Projection
Category.Entry.COLUMN_NAME_PARENT_ID + " = ?", // Selection
new String[]{"0"}, // Selection args
null);
if (data != null) {
while(data.moveToNext()){
categories.add(new Category(data));
}
}
TabsPagerAdapter mAdapter = new TabsPagerAdapter(getActivity().getSupportFragmentManager(), this.getActivity(), categories);
mViewPager.setAdapter(mAdapter);
mTabsHost.setupWithViewPager(mViewPager);
}