i have a ViewPager that has a Fragment which contains a GridView into it
my code works fine only when i'm scrolling page with delay and each time retrieve's content's from internet again
all i want to do is just get each page content's once and use it when user scroll's a page
one of my issues is that JSON downloding simultaneously when several pages has been scrolled and i don't know how to store my gridview content's for next usage that a page called
is there a standard way to conquer this issue ?
here is PagerAdapter for my ViewPager :
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
String[] tabName;
public ViewPagerAdapter(FragmentManager fm, String[] tabArray) {
super(fm);
this.tabName = new String[tabArray.length];
this.tabName = tabArray;
}
#Override
public Fragment getItem(int position) {
TabPageFragment tabPageFragment = new TabPageFragment(position);
return tabPageFragment;
}
#Override
public int getCount() {
return tabName.length;
}
#Override
public CharSequence getPageTitle(int position) {
return tabName[position];
}
}
each page of ViewPager use's this class for populate Fragment :
public class TabPageFragment extends Fragment {
private GridView mgridview; // gridView inside Fragment
private int tabPosition;
private ArrayAdapterGridview arrayadapter; //adapter for my gridView
public TabPageFragment(int tabposition) {
this.tabPosition = tabposition;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mgridview = (GridView) rootView.findViewById(R.id.gridView2);
View rootView = inflater.inflate(R.layout.fragment_grid_view, container,false);
DownloadContentTab dct = new DownloadContentTab();
dct.execute();
return rootView;
}
// DownloadJSON AsyncTask
private class DownloadContentTab extends AsyncTask<Void, Void, Integer> {
#Override
protected Integer doInBackground(Void... params) {
JSONfunctions jsf = new JSONfunctions(); //this function retrieve's json for me
JSONArray jsonarray = jsf.getJSONfromURL(myUrl); // this url is differ for each page
String[] gridNameArray = new String[jsonarray.length()];
String[] gridPicArray = new String[jsonarray.length()];
for (int j = 0; j < jsonarray.length(); j++) {
try {
JSONObject jsonobject = jsonarray.getJSONObject(j);
gridNameArray[j] = jsonobject.getString("title");
gridPicArray[j] = jsonobject.getString("pic");
} catch (JSONException e) {
e.printStackTrace();
}
}
arrayadapter = new ArrayAdapterGridview(context, gridPicArray, gridNameArray);
return 0;
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
mgridview.setAdapter(arrayadapter);
}
}
}
Related
I'm trying to add tabs to my TabLayout-ViewPager-Fragment based application dynamically.The TabLayout uses a custom view with an ImageView on top of a TextView.
What I want now is to add tabs according to the number of JSONObjects in my JSONArray created from a PHP/MySQL web service. I tried the method below in my PagerAdapter but it throws:
java.lang.IllegalStateException: Can't change tag of fragment TstFrag{df80bc8 #0 id=0x7f080157 android:switcher:2131231063:0}: was android:switcher:2131231063:0 now android:switcher:2131231063:1.
The method is as in my Adapter below
public class FrgAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragmentList = new ArrayList<>();
private List<String> mFragmentTitleList = new ArrayList<>();
public FrgAdapter(FragmentManager fm) {
super(fm);
}
public FrgAdapter(FragmentManager fm, List<Fragment> mFragmentList, List<String> mFragmentTitleList) {
super(fm);
this.mFragmentList = mFragmentList;
this.mFragmentTitleList = mFragmentTitleList;
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public void insertFromJSONObject(JSONObject jsonObject, Fragment fragment, CircularImageView imageView, TextView textView) throws JSONException {
JSONArray dataArray = jsonObject.getJSONArray("data");
for (int i = 0; i < dataArray.length(); i++) {
JSONObject sectionObj = (JSONObject) dataArray.get(i);
JSONArray sectionsArray = sectionObj.getJSONArray("section");
for (int j = 0; j < sectionsArray.length(); j++) {
JSONObject obj = (JSONObject) sectionsArray.get(j);
Picasso.get().load(obj.getString("imag")).into(imageView);
mFragmentList.add(fragment);
mFragmentTitleList.add(obj.getString("name"));
textView.setText(obj.getString("name"));
notifyDataSetChanged();
}
}
}
#Override
public CharSequence getPageTitle(int position) {
return null;
}}
Here is where the method is called in my activity to add the fragments:
private void setUpViewPager(ViewPager viewPager, View view) {
adapter = new FrgAdapter(getSupportFragmentManager());
/*adapter.addFragment(new MleFrag(), "Men");
adapter.addFragment(new FmlFrag(), "Women");
adapter.addFragment(new ChdFrag(), "Children");
adapter.addFragment(new AceFrag(), "Accessories");
*/
String url = "https://44091ee6.ngrok.io/Glam/men.json";
AndroidNetworking.get(url)
.setPriority(Priority.MEDIUM)
.build()
.getAsJSONObject(new JSONObjectRequestListener() {
#Override
public void onResponse(JSONObject response) {
try {
adapter.insertFromJSONObject(response, new TstFrag(), view.findViewById(R.id.circularImageView), view.findViewById(R.id.text_header));
adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onError(ANError anError) {
Toast.makeText(getApplicationContext(), anError.toString(), Toast.LENGTH_LONG).show();
}
});
adapter.notifyDataSetChanged();
viewPager.setAdapter(adapter);
}
and here is my Fragment. In my mind I want to reuse this one Fragment for each of the times I will be requiring one.
public class TstFrag extends Fragment {
public TstFrag() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.layout_cht, container, false);
}}
You may try this:
adapter.insertFromJSONObject(response, view.findViewById(R.id.circularImageView), view.findViewById(R.id.text_header));
adapter.notifyDataSetChanged();
and
public void insertFromJSONObject(JSONObject jsonObject, CircularImageView imageView, TextView textView) throws JSONException {
JSONArray dataArray = jsonObject.getJSONArray("data");
for (int i = 0; i < dataArray.length(); i++) {
JSONObject sectionObj = (JSONObject) dataArray.get(i);
JSONArray sectionsArray = sectionObj.getJSONArray("section");
for (int j = 0; j < sectionsArray.length(); j++) {
JSONObject obj = (JSONObject) sectionsArray.get(j);
Picasso.get().load(obj.getString("imag")).into(imageView);
mFragmentList.add(new TstFrag());
textView.setText(obj.getString("name"));
//mFragmentTitleList.add(obj.getString("name"));
notifyDataSetChanged();
}
}
}
The basic idea here is to create a new instance of TstFrag for each entry of the FrgAdapter.
Consider NOT to add fragments to viewPager manually but just implement getItem && instantiateItem methods on viewPager adapter. Then viewPager will control the instantiation of new TstFrag or just reuse created one. Check this answer for complete adapter.
#Override
public Fragment getItem(final int pos) {
return TstFrag.getInstance(dataList.get(pos));
}
#NonNull
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
Update
public class DataModel implements Serializable{
private String name;
private String image;
// GETTER && SETTER
}
Replace
private List<String> mFragmentTitleList = new ArrayList<>();
With
private List<DataModel> dataList = new ArrayList<>();
insertFromJSONObject
dataList.clear();
for (int j = 0; j < sectionsArray.length(); j++) {
JSONObject obj = (JSONObject) sectionsArray.get(j);
final DataModel model = new DataModel();
model.setName(obj.getString("name"));
model.setImage(obj.getString("imag"));
// Picasso.get().load(obj.getString("imag")).into(imageView);
// No need to load image here just fetch for cache if you want.
Picasso.get().load(model.getImage()).fetch();
// mFragmentList.add(fragment); // no need handle adding fragment here as mentioned above.
dataList.add(dataModel);
// textView.setText(obj.getString("name")); // It's not good to update UI here but update there with fragment on create called mention below.
// notifyDataSetChanged(); DON'T call this inside the loop but after finish your stuff.
}
// Just notify here...
notifyDataSetChanged();
TstFrag
public class TstFrag extends Fragment {
private DataModel model;
public TstFrag() {
}
public static TstFrag getInstance(DataModel model){
TstFrag fragment = new TstFrag();
Bundle bundle = new Bundle();
bundle.putSerializable("mData", model);
fragment.setArguments(bundle);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = (DataModel)getArguments().getSerializable("mData");
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.layout_cht, container, false);
// findViewById() for imageView and nameTextView
Picasso.get().load(model.getImage()).into(imageView);
nameTextView.setText(model.getName());
}}
Hi I have Tablayout with Viewpager and i am using Fragment for tablayout. Now in every Tablayout fragments I have Recyclerview and displaying items.Please See this my json response
http://pastebin.com/nUswad9s
here in "typeMaster": array i have categories "typeName": "Dogs", and i am displaying typenames in tablayout i have 4 tablayout, and inside typemaster i have subcategoreis named "catMaster": and i am trying to display catmaster data in recyclerview,but the issue is in every fragment it shows last data "catName": "Vitamins & Minerals",
Activity
public class CategoriesActivity extends AppCompatActivity{
private Header myview;
private ArrayList<SubcategoryModel> subct;
private ArrayList<CategoryModel> filelist;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.categoris_activity);
filelist = (ArrayList<CategoryModel>)getIntent().getSerializableExtra("categorylist");
System.out.println("Category list size"+filelist.size());
myview = (Header) findViewById(R.id.categorisactivity_headerView);
myview.setActivity(this);
TabLayout tabLayout = (TabLayout) findViewById(R.id.cat_tab_layout);
for(int i = 0; i < filelist.size(); i++){
subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
System.out.println("SubCategory list size"+subct.size());
}
for(int i = 0; i < filelist.size(); i++){
tabLayout.addTab(tabLayout.newTab().setText(filelist.get(i).getCategory_typename()));
ArrayList<SubcategoryModel> subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
}
Bundle bundleObject = new Bundle();
bundleObject.putSerializable("key", filelist);
FirstFragment ff=new FirstFragment();
ff.setArguments(bundleObject);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager) findViewById(R.id.categories_pager);
CategoriesAdapter mPagerAdapter = new CategoriesAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(mPagerAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
public class CategoriesAdapter extends FragmentStatePagerAdapter {
ArrayList<CategoryModel> catlist;
int numoftabs;
public CategoriesAdapter(FragmentManager fm, int numoftabs) {
super(fm);
this.numoftabs = numoftabs;
}
#Override
public Fragment getItem(int position) {
Log.v("adapter", "getitem" + String.valueOf(position)+subct.size());
return FirstFragment.create(position,subct);
}
#Override
public int getCount() {
return numoftabs;
}
}
}
Fragment
public class FirstFragment extends Fragment {
// Store instance variables
public static final String ARG_PAGE = "page";
private int mPageNumber;
private Context mContext;
private int Cimage;
private ArrayList<SubcategoryModel> subcatlist;
private RecyclerView rcylervw;
private ArrayList<CategoryModel> filelist;
ArrayList<SubcategoryModel> subct;
public static FirstFragment create(int pageNumber,ArrayList<SubcategoryModel> subct){
FirstFragment fragment = new FirstFragment();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, pageNumber);
args.putSerializable("key", subct);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPageNumber = getArguments().getInt(ARG_PAGE);
subct= (ArrayList<SubcategoryModel>) getArguments().getSerializable("key");
System.out.println("Frag Category list size"+subct.size());
/* for(int i = 0; i < filelist.size(); i++){
subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
System.out.println("Frag SubCategory list size"+subct.size());
}*/
// image uri get uri of image that saved in directory of app
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater
.inflate(R.layout.test, container, false);
rcylervw=(RecyclerView)rootView.findViewById(R.id.subcategory_recycler_view);
rcylervw.setHasFixedSize(true);
MyAdapter adapter = new MyAdapter(subct);
rcylervw.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rcylervw.setLayoutManager(llm);
return rootView;
}
// this method is not very important
}
MyAdapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private ArrayList<SubcategoryModel> mDataset;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public MyViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.subcategory_text);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<SubcategoryModel> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_subcategory, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.mTextView.setText(mDataset.get(position).getSubCategory_name());
}
#Override
public int getItemCount() {
return mDataset.size();
}
}
Output i am getting right now
As you can see it shows same result "Vitamin & Minerals" in every tabs..i want different subcategories instead of same.
I see a lot of problems with your code, but let's get your UI displaying the subcategories since that's your main concern.
Change the getItem in your adapter to this:
#Override
public Fragment getItem(int position) {
ArrayList<SubcategoryModel> subcategories = filelist.get(position).getItems();
Log.v("adapter", "getitem" + String.valueOf(position)+subcategories.size());
return FirstFragment.create(position,subcategories);
}
What caused the problem:
Let's focus on ArrayList<SubcategoryModel> subct in your activity:
First your code did this:
for(int i = 0; i < filelist.size(); i++){
ArrayList<SubcategoryModel> subct=filelist.get(i).getItems();
// for(int j=0;j<subct.size();j++) ...
}
So at the end of this loop subct is set the subcategories of the last category in filelist.
After that, you did another loop to load the tabs, but that used a different subct variable that was declared inside the loop, and that had no effect on the subct field of your activity.
Then you created your view pager and adapter.
In your pager adapter you had this:
#Override
public Fragment getItem(int position) {
Log.v("adapter", "getitem" + String.valueOf(position)+subct.size());
return FirstFragment.create(position,subct);
}
Since subct was set to the last category's subcategories from the loop before, every single fragment created was receiving those subcategories, no matter what position (category) the fragment was for. All I did was change the code to go back to filelist and get the correct category (and subcategories) for the position of the fragment being created.
When you're writing code, you think about what you want the code to do. However, at the point where you run the code and discover you have a problem, you have to forget what you wanted the code to do, then pretend you're the computer and run the code in your head. You want to understand what effect every line of code is having. When you do it that way it's easier to find the problem.
Problem:
There's no way to pass a Serializable ArrayList in a Bundle. Look at the docs page here Bundle docs
Solution:
Change your SubCategoryModel to implement Parcelable and then use bundle.putParcelableArrayList(key, list) and bundle.getParcelableArrayList(key) to pass the ArrayList to the FragmentArgs and get them from the Fragment
this is the main logic of your code I guess... Try it and let me know if you need more help or you find it helpful...
private void parseJsonData() {
try {
listDogs.clear();
JSONArray jsonArray = new JSONArray(loadJSONFromAsset());
JSONObject firstJsonobject = jsonArray.optJSONObject(0);
JSONArray itemListJsonArray = firstJsonobject.optJSONArray("itemList");
JSONObject secondJsonobject = itemListJsonArray.optJSONObject(0);
JSONArray typeMasterArray = secondJsonobject.optJSONArray("typeMaster");
JSONObject thirdJsonobject = typeMasterArray.optJSONObject(0);
JSONArray catMasterArray = thirdJsonobject.optJSONArray("catMaster");
for(int i=0; i<catMasterArray.length(); i++) {
JSONObject jsonObject = catMasterArray.optJSONObject(i);
ModelClass modelClass = new ModelClass();
modelClass.setTypeId(jsonObject.optString("catID"));
modelClass.setTypeName(jsonObject.optString("catName"));
listDogs.add(modelClass);
}
RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(getActivity(), listDogs);
recyclerView.setAdapter(recyclerViewAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
Note: To parse data for dogs category I've passed 0 position in variable thirdJsonobject. Pass 1 for cats and 2 for horse and you will find your desired output
Screenshots:
Dogs category
Cats category
Horse category
i want to know if we can develop tabs using JSON.i want as many tabs depending upon the categories in JSON and each tab must contain the list view if it is possible please let me know how to do it please
MainActivity.class
private void catmethod(){
String url="http://www.souqalkhaleejia.com/webapis/menus.php";
JsonObjectRequest catreq=new JsonObjectRequest(Request.Method.GET, url, (String) null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray menuarray=response.getJSONArray("menu");
for (int i=0;i<menuarray.length();i++){
JSONObject menuobj=menuarray.getJSONObject(i);
tabs.addTab(tabs.newTab().setText(menuobj.getString("title")));
Toast.makeText(MainActivity.this, menuobj.getString("title"), Toast.LENGTH_SHORT).show();
}
TabsAdapter tabsAdapter=new TabsAdapter(getSupportFragmentManager(),menuarray.length());
viewpager.setAdapter(tabsAdapter);
tabs.setupWithViewPager(viewpager);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("CatMenu", String.valueOf(error));
}
});
AppController.getInstance().addToRequestQueue(catreq);
}
Your fragment
public class OneFragment extends Fragment{
public OneFragment() {
// Required empty public constructor
}
public static Fragment getInstance(int position){
OneFragment fragment = new OneFragment();
Bundle bundle = new Bundle();
bundle.putInt("position", position)
fragment.setArgument(bundle);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_one, container, false);
int position = getArguments().getInt("position", 0);
// set your list base on position
if(position == 0){
//list 1
} else if(position == 1) {
// list 2
} else {
// list 3
}
return view;
}
}
Your ViewPagerAdapter
class ViewPagerAdapter extends FragmentPagerAdapter {
private JSONArray jsonArray;
public ViewPagerAdapter(FragmentManager manager, JSONArray jsonArray) {
super(manager);
this.jsonArray= jsonArray;
}
#Override
public Fragment getItem(int position) {
return OneFragment.getInstance(position);
}
#Override
public int getCount() {
return jsonArray.length();
}
#Override
public CharSequence getPageTitle(int position) {
return jsonArray.getJSONObject(position).getString("key");
}
}
Tablayout setup
tabLayout = (TabLayout) findViewById(R.id.tabs);
// get your json list
JSONArray jsonArray = your_json_array;
for(int i = 0; i < yourJsonArray.length(); i++){
JSONObject json = yourJsonArray.get(i);
tabLayout.addTab(tabLayout.newTab().setText(json.getString("key")));
}
viewPager = (ViewPager) findViewById(R.id.viewpager);
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager(), yourJsonArray);
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
//JSON => [{"key":"TAB1", "list":[your list]}, {"key":"TAB2", "list":[your list]}, {"key":"TAB3", "list":[your list]}]
Using JSON you can add tab dynamically like...
tabLayout = (TabLayout) findViewById(R.id.tabs);
// get your json list
JSONArray jsonArray = your_json_array;
for(int i = 0; i < yourJsonArray.length(); i++){
JSONObject json = yourJsonArray.get(i);
tabLayout.addTab(tabLayout.newTab().setText(json.getString("key")));
}
Now using ViewPager you can display your list into Fragment base on your tab position.
This link will helpful to setup TabLayout android-material-design-working-with-tabs
You can also your google Gson library to parse your JSON object.
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);
}
i'm developing an app with viewpagerindicator and actionsherlock. I've implemented a tab screen but when i load data in a SherlockListFragment Async, fragments dissapear after few fragment changes.
I've four tabs A,B,C,D and when i load data async switching A to B is ok, but when i switch to C, A doesn't show fragment and when i switch to D no fragment is displayed any more.
No error is thrown.
My Fragment page adapter is like this:
class PaginationAdapter extends FragmentPagerAdapter {
public PaginationAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return new CustomFragment();
}
#Override
public CharSequence getPageTitle(int position) {
return CONTENT[position % CONTENT.length].toUpperCase(Locale.getDefault());
}
#Override
public int getCount() {
return CONTENT.length;
}
}
This is the fragment that works:
public final class CustomFragment extends SherlockListFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new SimpleAdapter(getSherlockActivity(), getData(),
R.layout.descuentos_layout, new String[] { "title" },
new int[] { R.id.txtTitle }));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.custom_list_fragment, null);
return view;
}
protected List<Map<String, String>> getData() {
List<Map<String, String>> myData = new ArrayList<Map<String, String>>();
for (int i = 1; i < 20; i++){
Map<String, String> temp = new HashMap<String, String>();
temp.put("title", "Item " + i);
temp.put("ItemId", String.valueOf(i));
myData.add(temp);
}
return myData;
}
}
But this doesn't:
public final class DescuentosFragment extends SherlockListFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListViewLoaderTask llt = new ListViewLoaderTask();
llt.execute("");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.descuentos_list_fragment, null);
return view;
}
private class ListViewLoaderTask extends AsyncTask<String, Void, SimpleAdapter> {
#Override
protected SimpleAdapter doInBackground(String... str) {
SimpleAdapter adapter = new SimpleAdapter(getSherlockActivity(), getData() , R.layout.descuentos_layout,new String[] { "title" },
new int[] { R.id.list_title });
return adapter;
}
#Override
protected void onPostExecute(SimpleAdapter adapter) {
ListView listView = getListView();
listView.setAdapter(adapter);
}
protected List<Map<String, String>> getData() {
List<Map<String, String>> myData = new ArrayList<Map<String, String>>();
for (int i = 1; i < 20; i++){
Map<String, String> temp = new HashMap<String, String>();
temp.put("title", "Item " + i);
temp.put("ItemId", String.valueOf(i));
myData.add(temp);
}
return myData;
}
}
}
What is wrong? thx