I have 2 fragments, both work with array adapter to display their category. First fragment is display item category, second fragment is display job category. However, it display the job category in both fragment. I don't know which part is going wrong.
This is my ViewPager to display the fragment when the user select the corresponding tab. The setCategory() will called when received the data from database.
public class ViewPagerAdapter extends FragmentPagerAdapter {
private List<Category> categoryList = new ArrayList();
private DisplayItemFragment itemFragment;
private DisplayJobFragment jobFragment;
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Log.d("categoryList", categoryList.size()+" ");
if (position ==0) {
itemFragment = new DisplayItemFragment(categoryList);
return itemFragment;
}else{
jobFragment = new DisplayJobFragment(categoryList);
return jobFragment;
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position){
//
//Your tab titles
//
case 0:return "Item";
case 1:return "Job";
default:return null;
}
}
public void setCategory(List<Category> list){
List<Category> tempList = new ArrayList();
for(int i=0;i<list.size();i++){
if(list.get(i).getType().equals("item")){
tempList.add(list.get(i));
}
}
itemFragment.update(tempList);
Log.d("this.categoryListitem",tempList.size()+"");
tempList.clear();
for(int i=0;i<list.size();i++){
if(list.get(i).getType().equals("job")){
tempList.add(list.get(i));
}
}
jobFragment.update(tempList);
Log.d("this.categoryListjob",tempList.size()+"");
}
}
This is the fragment to display item category
public class DisplayItemFragment extends Fragment {
private View rootView;
private GridView gridView;
private List<Category> categoryList;
private DisplayFragmentPresenter presenter;
private CategoryGridAdapter categoryAdapter;
private TextView text;
public DisplayItemFragment(List<Category> categoryList) {
this.categoryList=categoryList;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_display, container, false);
text = (TextView) rootView.findViewById(R.id.test);
categoryAdapter = new CategoryGridAdapter(getActivity(), R.layout.fragment_display, categoryList);
gridView = (GridView) rootView.findViewById(R.id.gridview);
gridView.setAdapter(categoryAdapter);
gridView.setTextFilterEnabled(true);
//Log.d("category",categoryList.get(0).getName());
return rootView;
}
public void update(List<Category> list) {
this.categoryList.clear();
for(int i=0;i<list.size();i++){
if(list.get(i).getType().equals("item")){
this.categoryList.add(list.get(i));
}
}
text.setText("item refresh");
for(int i=0;i<this.categoryList.size();i++){
Log.d("categoryListitem",categoryList.get(i).getName());
}
}
This is the fragment to display job category
public class DisplayJobFragment extends Fragment {
private View rootView;
private GridView gridView;
private List<Category> categoryList;
private DisplayFragmentPresenter presenter;
private TextView text;
private CategoryGridAdapter categoryAdapter;
public DisplayJobFragment(List<Category> categoryList) {
this.categoryList=categoryList;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_display, container, false);
text = (TextView) rootView.findViewById(R.id.test);
categoryAdapter = new CategoryGridAdapter(getActivity(), R.layout.fragment_display, categoryList);
gridView = (GridView) rootView.findViewById(R.id.gridview);
gridView.setAdapter(categoryAdapter);
gridView.setTextFilterEnabled(true);
//Log.d("category",categoryList.get(0).getName());
return rootView;
}
public void update(List<Category> list) {
this.categoryList.clear();
for(int i=0;i<list.size();i++){
if(list.get(i).getType().equals("job")){
this.categoryList.add(list.get(i));
}
}
text.setText("job refresh");
//categoryAdapter = new CategoryGridAdapter(getActivity(), R.layout.fragment_display, this.categoryList);
for(int i=0;i<this.categoryList.size();i++){
Log.d("categoryListjob",categoryList.get(i).getName());
}
}
}
Both fragment will called CategoryGridAdapter to display category on gridview
public class CategoryGridAdapter extends ArrayAdapter<Category> {
private List<Category> categoryList;
private Context context;
public CategoryGridAdapter(Context context, int resource, List<Category> categoryList) {
super(context, resource, categoryList);
this.context = context;
this.categoryList = categoryList;
}
#Override
public boolean isEnabled(int position) {
return true;
}
#Override
public int getCount() {
return ((null != categoryList) ?
categoryList.size() : 0);
}
#Override
public Category getItem(int position) {
return ((null != categoryList) ?
categoryList.get(position) : null);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
LayoutInflater layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (null == view) {
view = layoutInflater.inflate(R.layout.grid_category, null);
}
final Category category = categoryList.get(position);
Log.d("categorygridlist",category.getName()+" "+position+ " " + categoryList.size());
if (category != null) {
final CardView categoryGridLayout = (CardView) view.findViewById(R.id.category_gridlayout);
final TextView categoryName = (TextView) view.findViewById(R.id.category_name);
final ImageView categoryIcon = (ImageView) view.findViewById(R.id.category_icon);
categoryName.setText(category.getName());
categoryName.setSelected(true);
try {
byte[] decodedString = Base64.decode(category.getImage(), Base64.DEFAULT);
BitmapFactory.Options options=new BitmapFactory.Options();// Create object of bitmapfactory's option method for further option use
options.inPurgeable = true; // inPurgeable is used to free up memory while required
Bitmap decodedByte1 = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);//Decode image, "thumbnail" is the object of image file
Bitmap decodedByte = Bitmap.createScaledBitmap(decodedByte1, 50 , 50 , true);// convert decoded bitmap into well scalled Bitmap format.
categoryIcon.setImageBitmap(decodedByte);
} catch (Exception e) {
e.printStackTrace();
}
categoryGridLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "worked", Toast.LENGTH_LONG).show();
}
});
}
return view;
}
I expect it will display item category at view pager when user select item tab and job category at view pager when user select job tab but it only display the job category. Anyone got solutions about this? Thanks
In the ViewPagerAdapter class, you have a List<Category> categoryList that you're passing to both Fragments in their constructors, and each Fragment is setting that same list as its dataset. The log prints you have in the setCategory() and update() methods only seem correct, because the updates are happening sequentially, and you're clearing the list in between.
Instead of passing that List to each Fragment, just have each one create its own new ArrayList<Category>, and remove that parameter from each constructor.
Related
MensWearResponse could not be imported. I tried the api and only the fragment is showing many errors. I am a news developer. If you know, I need to fix this error. I have given the image below. Picasso.with(context).load(imageUrlFromServer+mensWear.getFirst_wear()).into(imageView); These include errors
public class Phones extends Fragment {
private GridView gridView;
private List<Category> mensWears;
private GalleryAdapter adapter;
public Phones() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_phones,container,false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view,savedInstanceState);
gridView = view.findViewById(R.id.gridHolder);
gridView = view.findViewById(R.id.gridHolder);
Call<MensWearResponse> wearResponseCall =
Service.getInstance().getApi().getAllMensWears();
wearResponseCall.enqueue(new Callback<MensWearResponse>() {
#Override
public void onResponse(Call<MensWearResponse> call,Response<MensWearResponse> response) {
mensWears = response.body().getMensWears();
for (MensWear mwr : mensWears){
Log.d("Name", mwr.getFirst_wear());
}
adapter = new Category(getActivity(), mensWears);
gridView.setAdapter(adapter);
}
#Override
public void onFailure(Call<MensWearResponse> call,Throwable t) {
}
});
}
}
adapter
public class GalleryAdapter extends BaseAdapter {
private Context context;
private List<Category> mensWears;
public String imageUrlFromServer = "http:/10.0.2.2:5757/api/public/images/";
public GalleryAdapter(Context context, List<Category> mensWears) {
this.context = context;
this.mensWears = mensWears;
}
#Override
public int getCount() {
return mensWears.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i,View view,ViewGroup viewGroup) {
final Category mensWear = mensWears.get(i);
if (view == null) {
final LayoutInflater layoutInflater = LayoutInflater.from(context);
view = layoutInflater.inflate(R.layout.custom_gallery_layout, null);
}
//For text
TextView prdId = view.findViewById(R.id.);
prdId.setText(prdId.toString());
//For images
final ImageView imageView = view.findViewById(R.id.name);
if(!TextUtils.isEmpty(mensWear.getItemName())){
Picasso.with(context).load(imageUrlFromServer+mensWear.getFirst_wear())
.into(imageView);
}
return view;
}
}
I'm trying to figure out how I would display Bundle data that I have in my fragment and display it in a RecyclerView. In the onClick method of my activity, I get the input from the user and wrap the values in a Bundle. I then send it to the fragment to be displayed in the RecyclerView. I'm a bit stumped on how I would go about setting up my RecyclerView Adapter to display the Bundle data Any help would be greatly appreciated. I can show data in recyclerview but i can display just 1 item i want to show more item when i sending data from activity to fragment.
This is my Fragment
public class BlankFragment extends Fragment {
List<Mydata> mydataList = new ArrayList<>();
public BlankFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View vi = inflater.inflate(R.layout.fragment_blank, container, false);
RecyclerView recyclerView = vi.findViewById(R.id.recyclerShop);
Bundle extras = this.getArguments();
if(extras != null)
{
String nameExtra = extras.getString("name");
String amountExtra = extras.getString("color");
//Just add your data in list
Mydata mydata = new Mydata(); // object of Model Class
mydata.setAmountExtra(amountExtra );
mydata.setNameExtra(nameExtra);
mydataList.add(mydata);
}
MyAdapter myAdapter = new MyAdapter(getContext());
myAdapter.setMyDataList(mydataList);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return vi;
}
}
Here is the Adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private Context context;
private List<Mydata> myDataList;
public MyAdapter(Context context) {
this.context = context;
myDataList = new ArrayList<>();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Replace with your layout
View view = LayoutInflater.from(context).inflate(R.layout.shop_item_layout, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Set Your Data here to yout Layout Components..
holder.tvName.setText(myDataList.get(position).getNameExtra());
holder.tvColor.setText(myDataList.get(position).getAmountExtra());
// to get Amount
// myDataList.get(position).getAmountExtra();
}
#Override
public int getItemCount() {
if (myDataList.size() != 0) {
// return Size of List if not empty!
return myDataList.size();
}
return 0;
}
public void setMyDataList(List<Mydata> myDataList) {
// getting list from Fragment.
this.myDataList = myDataList;
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageShop;
TextView tvName,tvColor,tvamount;
EditText etBodySize,etAllAmount;
public ViewHolder(View itemView) {
super(itemView);
imageShop = itemView.findViewById(R.id.imgShop);
tvName = itemView.findViewById(R.id.tvClothesName);
tvColor =itemView.findViewById(R.id.tvColor);
tvamount = itemView.findViewById(R.id.tvfiyat);
etBodySize = itemView.findViewById(R.id.etAmount);
etAllAmount = itemView.findViewById(R.id.etAllAmount);
// itemView.findViewById
}
}
}
Lastly here is the MyData Class
public class Mydata {
String nameExtra;
String amountExtra;
public Mydata(String nameExtra, String amountExtra) {
this.nameExtra = nameExtra;
this.amountExtra = amountExtra;
}
public Mydata() {
}
public String getAmountExtra() {
return amountExtra;
}
public void setAmountExtra(String amountExtra) {
this.amountExtra = amountExtra;
}
public String getNameExtra() {
return nameExtra;
}
public void setNameExtra(String nameExtra) {
this.nameExtra = nameExtra;
}
}
Then when i sending data and open fragment
blankFragment = new BlankFragment();
Bundle bundle = new Bundle();
bundle.putString("name",clothesRecycler.data.get(position).getName());
bundle.putString("color",clothesRecycler.data.get(position).getColor());
blankFragment.setArguments(bundle);
manager = getSupportFragmentManager();
manager.beginTransaction().add(R.id.container,blankFragment).addToBackStack(null).commit();
Add exras.hasExtras() in your name extras, then getStringExtra() and add break point to see if you are passing valid data. I am assuming you are not retrieving the data you expect. I see no problem with the adapter.
if(this.getArguments().hasExtras("name") && this.getArguments().hasExtras("color")){
//do whatever
}
I have a MainActivity which first makes a call to my server and gets the response. Then, on the success of first response, i am initiating the viewPager.
Below, code is called to initiate the viewPager and it's adapter, it is called only after the success of first response.
mShowTimeViewPageAdapter = new ShowTimeViewPageAdapter(getSupportFragmentManager(), getApplicationContext(), this, mDateStringList, showDateCodesList, venueHashMap);
mVenueHashMap = venueHashMap;
mRequestedDateCodes = requestedDateCodes;
mViewPager.setAdapter(mShowTimeViewPageAdapter);
mShowTimeTabLayout.setupWithViewPager(mViewPager);
for (int i = 0; i < range; i++) {
TabLayout.Tab tab = mShowTimeTabLayout.getTabAt(i);
tab.setCustomView(mShowTimeViewPageAdapter.getTabView(i));
}
This is my viewPagerAdapter.
public class ShowTimeViewPageAdapter extends FragmentStatePagerAdapter {
private static final String TAG = ShowTimeViewPageAdapter.class.getSimpleName();
private Map<Integer, String> mFragmentTags;
private Context mContext;
private List<String> mDateStringList;
private FragmentManager fragmentManager;
private IShowTimeActivity mIShowTimeActivity;
private List<String> mDateCodes;
private LinkedHashMap<String, List<Venue>> mVenueHashMap;
public ShowTimeViewPageAdapter(FragmentManager fm, Context context, IShowTimeActivity showTimeActivity, List<String> createdDates, List<String> dateCodes, LinkedHashMap<String, List<Venue>> venueHashMap) {
super(fm);
this.mContext = context;
this.mIShowTimeActivity = showTimeActivity;
this.fragmentManager = fm;
this.mDateCodes = dateCodes;
this.mVenueHashMap = venueHashMap;
this.mDateStringList = createdDates;
mFragmentTags = new HashMap<Integer, String>();
}
private List<Venue> getVenuesList(String dateCode) {
return mVenueHashMap.get(dateCode);
}
#Override
public Fragment getItem(int position) {
String stringDate = mDateStringList.get(position).split(";")[2];
if (mDateCodes.contains(stringDate)) {
if (getVenuesList(stringDate) == null) {
mIShowTimeActivity.requestForTheVenueListByDateCode(stringDate, position);
}
}
ShowTimeFragment showTimeFragment = ShowTimeFragment.newInstance(stringDate);
showTimeFragment.setVenueList(mVenueHashMap.get(stringDate));
// fragmentManager.beginTransaction().add(showTimeFragment, ""+position);
return showTimeFragment;
}
#Override
public int getCount() {
return mDateStringList.size();
}
public View getTabView(int position) {
String[] dateStr = mDateStringList.get(position).split(";");
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View tabView = layoutInflater.inflate(R.layout.show_time_tab_layout, null, false);
TextViewRoboto day = (TextViewRoboto) tabView.findViewById(R.id.show_time_tab_day);
TextViewRoboto date = (TextViewRoboto) tabView.findViewById(R.id.show_time_tab_date);
day.setText(dateStr[0]);
date.setText(dateStr[1]);
return tabView;
}
}
Here, on getItem() method callback of viewPager, it creates a new fragment for each position and checks if the data for the selected position is available or not. If yes, which will be obviously there for the first position, since it was called after success of first response, it will pass the data to the fragment.
If not, it will make a new api request to the server, to get the data.
Since viewPager caches 2 pages, in advance, it will make 2 requests and cache the data.
In each request, i am updating the hashMap with data.
This is my fragment, which is always initiated for each position.
public class ShowTimeFragment extends Fragment {
private static final String KEY_CODE = "date_key";
public ShowTimeRecyclerViewAdapter mShowTimeRecyclerViewAdapter;
#Bind(R.id.show_time_fragment_recycler_view) RecyclerView mShowTimeRecyclerView;
#Bind(R.id.show_time_fragment_no_data_text_view) TextViewRoboto mShowTimeNoDataTextView;
List<Venue> venueList = new ArrayList<Venue>();
public List<Venue> getVenueList() {
return venueList;
}
public void setVenueList(List<Venue> venueList) {
this.venueList = venueList;
}
private View view;
public ShowTimeFragment() {
}
public static ShowTimeFragment newInstance(String dateCode) {
Bundle bundle = new Bundle();
bundle.putString(KEY_CODE, dateCode);
ShowTimeFragment showTimeFragment = new ShowTimeFragment();
showTimeFragment.setArguments(bundle);
return showTimeFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.show_time_fragment, container, false);
ButterKnife.bind(this, view);
mShowTimeRecyclerViewAdapter = new ShowTimeRecyclerViewAdapter(venueList, getContext());
mShowTimeRecyclerView.setAdapter(mShowTimeRecyclerViewAdapter);
if (venueList != null && venueList.size() > 0) {
mShowTimeRecyclerView.setVisibility(View.VISIBLE);
mShowTimeNoDataTextView.setVisibility(View.GONE);
CustomLinearLayoutManager cl = new CustomLinearLayoutManager(getActivity(), 1, false);
mShowTimeRecyclerView.setLayoutManager(cl);
}
else{
mShowTimeNoDataTextView.setVisibility(View.VISIBLE);
mShowTimeRecyclerView.setVisibility(View.GONE);
mShowTimeNoDataTextView.setText("NO Data Available");
}
return view;
}
}
And Below is my recyclerViewAdapter, which is called from the fragment.
public class ShowTimeRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_RECOMMENDED = 0;
private static final int TYPE_GENERIC = 1;
public List<Venue> mVenueList;
private Context mContext;
public ShowTimeRecyclerViewAdapter(List<Venue> venueList, Context context) {
this.mVenueList = venueList;
this.mContext = context;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_RECOMMENDED) {
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View view = layoutInflater.inflate(R.layout.show_time_recycler_view_header_item_view, parent, false);
final RecommendedViewHolder recyclerViewHolder = new RecommendedViewHolder(view);
return recyclerViewHolder;
}
else if (viewType == TYPE_GENERIC) {
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View view = layoutInflater.inflate(R.layout.show_time_recycler_view_item, parent, false);
final ChildViewHolder viewHolder = new ChildViewHolder(view);
return viewHolder;
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Venue venue = mVenueList.get(position);
if (holder instanceof RecommendedViewHolder) {
TextViewRoboto cinemaHallName = ((RecommendedViewHolder) holder).mRecommendedShowTimeCinemaHallName;
cinemaHallName.setText(venue.getVenueName());
CustomGridView movieTimingGridView = ((RecommendedViewHolder) holder).mRecommendedMovieTimingGridView;
ImageView reserveIcon = ((RecommendedViewHolder) holder).mRecommendedMovieReserveImage;
if (venue.getCinemaUnpaidFlag().equals("Y")) {
reserveIcon.setVisibility(View.VISIBLE);
}
else {
reserveIcon.setVisibility(View.GONE);
}
ImageView mTicketIcon = ((RecommendedViewHolder) holder).mRecommendedMovieMTicketImage;
if (venue.getMTicket().equals("Y")) {
mTicketIcon.setVisibility(View.VISIBLE);
}
else {
mTicketIcon.setVisibility(View.GONE);
}
List<ShowTime> currShowTimesList = new ArrayList<ShowTime>(venue.getShowTimes());
movieTimingGridView.setAdapter(new ShowMovieTimeAdapter(mContext, currShowTimesList, true));
movieTimingGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
});
}
else if (holder instanceof ChildViewHolder) {
((ChildViewHolder) holder).mShowTimeCinemaHallName.setText(venue.getVenueName());
if (venue.getMTicket().toUpperCase().equals("Y") || venue.getCinemaUnpaidFlag().toUpperCase().equals("Y")) {
if (venue.getCinemaUnpaidFlag().toUpperCase().equals("N")) {
((ChildViewHolder) holder).mMovieReserveImage.setVisibility(View.GONE);
}
else if (venue.getCinemaUnpaidFlag().toUpperCase().equals("Y")) {
((ChildViewHolder) holder).mMovieReserveImage.setVisibility(View.VISIBLE);
((ChildViewHolder) holder).mMovieReserveImage.setImageResource(R.drawable.show_time_reserve_seat_icon);
}
if (venue.getMTicket().toUpperCase().equals("N")) {
((ChildViewHolder) holder).mMovieMTicketImage.setVisibility(View.GONE);
}
else if (venue.getMTicket().toUpperCase().equals("Y")) {
((ChildViewHolder) holder).mMovieMTicketImage.setVisibility(View.VISIBLE);
((ChildViewHolder) holder).mMovieMTicketImage.setImageResource(R.drawable.show_time_m_ticket_icon);
}
}
else {
((ChildViewHolder) holder).mShowTimeFragImagesLinearLayout.setVisibility(View.GONE);
}
CustomGridView movieTimingGridView = ((ChildViewHolder) holder).mMovieTimingGridView;
List<ShowTime> currShowTimesList = new ArrayList<ShowTime>(venue.getShowTimes());
movieTimingGridView.setAdapter(new ShowMovieTimeAdapter(mContext, currShowTimesList, false));
movieTimingGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
});
}
}
public static class ChildViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.show_time_fragment_cinema_hall_name)
TextViewRoboto mShowTimeCinemaHallName;
#Bind(R.id.show_movie_timings_grid_view)
CustomGridView mMovieTimingGridView;
#Bind(R.id.show_time_fragment_reserve_image)
ImageView mMovieReserveImage;
#Bind(R.id.show_time_fragment_m_ticket_image)
ImageView mMovieMTicketImage;
#Bind(R.id.show_time_fragment_images_lin_layout)
LinearLayout mShowTimeFragImagesLinearLayout;
public ChildViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
public void swap(List<Venue> venueList){
if(mVenueList!=null){
mVenueList.clear();
mVenueList.addAll(venueList);
} else {
mVenueList = venueList;
}
}
class RecommendedViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.show_time_recommendation_fragment_cinema_hall_name)
TextViewRoboto mRecommendedShowTimeCinemaHallName;
#Bind(R.id.show_movie_recommendation_timings_grid_view)
CustomGridView mRecommendedMovieTimingGridView;
#Bind(R.id.show_time_recommendation_fragment_reserve_image)
ImageView mRecommendedMovieReserveImage;
#Bind(R.id.show_time_recommendation_fragment_m_ticket_image)
ImageView mRecommendedMovieMTicketImage;
#Bind(R.id.show_time_recommendation_for_badge)
ImageView mShowTimeRecommendationBadge;
public RecommendedViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
#Override
public int getItemCount() {
return mVenueList.size();
}
#Override
public int getItemViewType(int position) {
if (isPositionRecommended(position))
return TYPE_RECOMMENDED;
return TYPE_GENERIC;
}
private boolean isPositionRecommended(int position) {
Venue venue = mVenueList.get(position);
return venue.isRecommended();
}
}
My problems lies here, even though the request is asynchronous, i want to show a loader, if the data hasn't come and the update the viewPager fragment on the data has come from server and hideLoading.
It's working fine when i am overriding getItemPosition() of viewPager and returning POSITION_NONE from there, but i don't want to do this, because it's recreating the fragment, and making my app slow.
I tried setting the TAG for each fragment and onPositionSelected() callback of viewPager listener, i tried swapping the recyclerView content for each fragment, but it didn't work.
Surprisingly, it loads all the data, if keep sliding to other pages and come back to 1st or 2nd page.
I tried all possible solution from my side.
Any kind suggestions would be appreciated.
This is how you keep your results, where you keep this is irrelevant
private LinkedHashMap<String, List<Venue>> mVenueHashMap;
And this is how you instantiate your fragment
ShowTimeFragment showTimeFragment = ShowTimeFragment.newInstance(stringDate);
You also want the fragment to load data if it is visible to user, if I am not mistaken, So you shall do the following in your fragment
public class ShowTimeFragment extends Fragment {
private String mStringDate; //obtained and stored here from pager adapter
private List<Venue> yourResults; // also obtained from pager adapter
#Override
public void onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.show_time_fragment, container, false);
ButterKnife.bind(this, view);
//at this point the progress bar should be visible.. view initilaisations are
//omitted to keep the code simple
if(yourResults != null){
//hide progress, show data
}
return view;
}
#Override
public void setUserVisibilityHint(boolean isVisibleToUser){
super.setUserVisibilityHint(isVisibleToUser)
//assuming you keep track of requests made for each dates in your activity
if(isVisibleToUser && yourResults== null &&
!myActivity.isRequestingForDate(mStringDate)){
// tell your activity here to load the data for this particular date
// if there is no data and there is no ongoing request for current date
}
}
#Override
public void onResume(){
super.onResume();
EventBus.getInstance().register(this);
}
#Override
public void onPause(){
super.onPause();
EventBus.getInstance().unregister(this);
}
#Subscribe
public void onVenueReceived(VenueResponse response){
if(mStringdate.equals(response.getDate())){
yourResult = response.getVenues();
// hide progressbar and show data here
}
}
}
and your VenueResponse class would look like this
public final class VenueResponse {
String date;
List<Venue> venues;
public VenueResponse(String date, List<Venue> venues) {
this.date = date;
this.venues = venues;
}
public List<Venues> getVenues(){
return venues;
}
public String getDate(){
return date;
}
}
in your activity, wherever you are receiving the network response, you would do the following to save and notify fragments
String date; // requested date
List<Venue> venues; // received from network call for a particular date
mVenueHashMap.put(date, venues); // saves to the hashmap you maintain
// if a fragment with this particular date is currentlly visible to user, it will
// receive the following broadcast. if not, it will get the cached
// response in `onCreateView()` lifecycle method when it becomes visible again
EventBus.getInstance().post(new VenueResponse(date, venues));
It is quiet a work but serves the purpose :)
I am working in project that I use Tablayout inside fragment , I have three tabs where they fetch data from web service , this part of the app show questions , we have three categories one for recent , second for un answered third for all question view
here is my situation my web developer design me web service return question item , they all share the same structure in returned item but data changed according to requirement .
public class Questions_Fragment extends Fragment {
private TabLayout mTablayout;
private ViewPager mViewpager;
public static Questions_Fragment newInstance() {
Questions_Fragment fragment = new Questions_Fragment();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.questions_layout, null);
mViewpager = (ViewPager) v.findViewById(R.id.viewPager);
setupViewPager(mViewpager);
mTablayout = (TabLayout) v.findViewById(R.id.tabs);
mTablayout.setupWithViewPager(mViewpager);
return v;
}
private void setupViewPager(ViewPager mViewpager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFrag( QuestionsFragModel.newInstance(VolleyRequestHandler.RECENT_INT) , getResources().getString(R.string.newest));
adapter.addFrag( QuestionsFragModel.newInstance(VolleyRequestHandler.UNANSWER_INT) , getResources().getString(R.string.notanswered));
adapter.addFrag( QuestionsFragModel.newInstance(VolleyRequestHandler.ALLPOSTS_INT) , getResources().getString(R.string.allposts));
mViewpager.setAdapter(adapter);
}
my view pager adapter class I extend FragmentStatePagerAdapter data could change each time user open tab
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragmentList = new ArrayList<>();
private List<String> mFragmentTitleList= new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fra , String title){
mFragmentList.add(fra);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
but I see it give me wrong view, it show image in question dont have image and it give answer to unanswered question
sorry for my long question but I want know what is wrong with my code ??
my list adapter
public class ListViewAdapter extends RecyclerView.Adapter<ListViewAdapter.ViewHolder> {
private Context _Context;
private List<QuestionItem> Questions = new ArrayList<>();
private API api;
private int num;
private int lastPosition = -1;
public static final String BASE_POST_URl = "url....";
public ListViewAdapter(Context context, List<QuestionItem> Questions) {
this._Context = context;
this.Questions = Questions;
api = new API(context);
}
public ListViewAdapter(Context context, List<QuestionItem> Questions,
int num) {
this._Context = context;
this.Questions = Questions;
this.num = num;
api = new API(context);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(_Context);
View itemView = inflater.inflate(R.layout.question_row, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
Typeface tf = Typeface.createFromAsset(_Context.getAssets(),
"fonts/GE_SS_Two_Bold.otf");
Typeface tfreg = Typeface.createFromAsset(_Context.getAssets(),
"fonts/GE_SS_Two_Light.otf");
ImageLoader _ImageLoader = MySingleton.getInstance(_Context).getmImageLoader();
if (Questions.get(position).user.userimageURL != null) {
if (!Questions.get(position).user.getUserimageURL().isEmpty()) {
//holder.userimageprog.setVisibility(View.VISIBLE);
holder.imageView.setImageUrl(Profile_Fragment.BASE_URL + Questions.get(position).user.getUserimageURL(), _ImageLoader);
}
}
if(Questions.get(position).Que_image_url != null){
if (!Questions.get(position).getQue_image_url().isEmpty()) {
holder._FrameLayout.setVisibility(View.VISIBLE);
holder.post_img.setVisibility(View.VISIBLE);
//holder.post_img_pro.setVisibility(View.VISIBLE);
holder.post_img.setImageUrl(BASE_POST_URl + Questions.get(position).getQue_image_url(), _ImageLoader);
}
}
holder.imageView.setDefaultImageResId(R.drawable.profile);
holder.username.setTypeface(tf);
holder.desc.setTypeface(tfreg);
holder.Date.setTypeface(tfreg);
holder.AnswersCount.setTypeface(tfreg);
if(Questions.get(position).user.username != null){
holder.username.setText(Questions.get(position).user.username);
}
if(Questions.get(position).Que_Content != null){
holder.desc.setText(Questions.get(position).Que_Content);
}
if(Questions.get(position).category != null){
holder.Category.setText(Questions.get(position).category);
}
if(Questions.get(position).Que_Date != null){
holder.Date.setText(Questions.get(position).Que_Date);
}
if (!Questions.get(position).getComment().isEmpty()) {
holder.arrow.setVisibility(View.VISIBLE);
holder.AnswersCount.setVisibility(View.VISIBLE);
holder.AnswersCount.setText(_Context.getResources().getString(R.string.youhaveanswer));
}
holder.arrow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent (_Context , ViewAnswers.class);
intent.putExtra("passedobject", (Parcelable) Questions.get(position));
_Context.startActivity(intent);
}
});
// Animation animation = null;
// animation = AnimationUtils.loadAnimation(_Context,
// R.anim.up_from_bottom);
// animation.setDuration(500);
// view.setAnimation(animation);
// animation = null;
//
// Animation animation = AnimationUtils.loadAnimation(_Context,
// (pos > lastPosition) ? R.anim.up_from_bottom
// : R.anim.down_from_top);
// view.startAnimation(animation);
// lastPosition = pos;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemCount() {
return Questions.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
protected NetworkImageView imageView, post_img;
protected TextView desc, Category, username, Date, AnswersCount;
protected ProgressBar userimageprog, post_img_pro;
protected ImageView arrow;
protected FrameLayout _FrameLayout;
public ViewHolder(View itemView) {
super(itemView);
imageView = (NetworkImageView) itemView.findViewById(R.id.ques_user_img);
desc = (TextView) itemView.findViewById(R.id.ques_content);
Category = (TextView) itemView.findViewById(R.id.category);
post_img = (NetworkImageView) itemView.findViewById(R.id.post_img);
userimageprog = (ProgressBar) itemView.findViewById(R.id.userimgae_prog);
post_img_pro = (ProgressBar) itemView.findViewById(R.id.post_prog);
username = (TextView) itemView.findViewById(R.id.username_ques);
Date = (TextView) itemView.findViewById(R.id.date);
AnswersCount = (TextView) itemView.findViewById(R.id.answers_con);
arrow = (ImageView) itemView.findViewById(R.id.imageView1);
_FrameLayout = (FrameLayout)itemView.findViewById(R.id.frameLayout2);
}
}
}
QuestionsFragModel view
public class QuestionsFragModel extends Fragment implements OnClickListener {
private RecyclerView Ques_list;
private ProgressBar list_prog;
private ListViewAdapter adapter;
private List<QuestionItem> Questions = new ArrayList<>();
private TextView reload;
private VolleyRequestHandler _VolleyRequestHandler;
private int CONST_TYPE = 0;
public static final String PASSED_INT = "passed_number";
private CoordinatorLayout _coordiatelayout;
static QuestionsFragModel newInstance(int type) {
QuestionsFragModel f = new QuestionsFragModel();
Bundle bundle = new Bundle();
bundle.putInt(PASSED_INT , type);
f.setArguments(bundle);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.question_layout, container, false);
CONST_TYPE = getArguments() != null ? getArguments().getInt(PASSED_INT) : 7;
_VolleyRequestHandler = new VolleyRequestHandler(getActivity());
_coordiatelayout = (CoordinatorLayout) v.findViewById(R.id.coordiatelayout);
Ques_list = (RecyclerView) v.findViewById(R.id.questionlist);
Ques_list.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter = new ListViewAdapter(getActivity(), Questions);
Ques_list.setAdapter(adapter);
list_prog = (ProgressBar) v.findViewById(R.id.progressbar);
reload = (TextView) v.findViewById(R.id.reload);
getQuestationsPosts();
reload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View position) {
getQuestationsPosts();
}
});
final FloatingActionButton floatingView = (FloatingActionButton) v.findViewById(R.id.FloatingView);
if (floatingView != null) {
floatingView.setOnClickListener(this);
}
return v;
}
public void getQuestationsPosts() {
API api = new API(getActivity());
if (api.isNetworkConnected()) {
list_prog.setVisibility(View.VISIBLE);
reload.setVisibility(View.GONE);
FetchQuestationsFromWeb();
} else {
Snackbar.make(_coordiatelayout, getResources().getString(R.string.nointernet), Snackbar.LENGTH_LONG).show();
Ques_list.setVisibility(View.GONE);
reload.setVisibility(View.VISIBLE);
}
}
private void onSuccessResponse(Object response){
list_prog.setVisibility(View.GONE);
reload.setVisibility(View.GONE);
Ques_list.setVisibility(View.VISIBLE);
if(Questions != null){
Questions.clear();
}
Questions = (List < QuestionItem>) response;
adapter = new ListViewAdapter(getActivity() ,Questions);
Ques_list.setAdapter(adapter);
}
private void onErrorResponse(String error){
list_prog.setVisibility(View.GONE);
reload.setVisibility(View.VISIBLE);
Snackbar.make(_coordiatelayout , error , Snackbar.LENGTH_LONG).show();
}
private void FetchQuestationsFromWeb() {
_VolleyRequestHandler.HandleRequests(Request.Method.POST , CONST_TYPE, null, new VolleyResponseCallBack() {
#Override
public void RequestSuccess(Object response) {
onSuccessResponse(response);
}
#Override
public void RequestFailed(String error) {
onErrorResponse(error);
}
});
}
#Override
public void onClick(View arg0) {
startActivity(new Intent(getActivity(), Add_Question.class));
}
}
I don't know why you use FragmentStatePagerAdapter instead of FragmentPagerAdapter when you have only 3 fragments.
AFAIK, FragmentStatePagerAdapter is better for performance if you have a large amount of fragments, because it don't stores the whole fragment in memory.
Anyway, FragmentStatePagerAdapter will save out your fragment's Bundle from savedInstanceState when it is destroyed. And when the user navigates back, the new fragment will be restored using the fragment's state.
So you need to check savedInstanceState before:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.question_layout, container, false);
if (savedInstanceState!=null){
// restore your state from "savedInstanceState"
} else{
CONST_TYPE = getArguments() != null ? getArguments().getInt(PASSED_INT) : 7;
}
}
If someone face some issue, it cause of I use if statement in adapter , simply you can use if only without else
Example I use if only
if (Questions.get(position).user.userimageURL != null) {
if (!Questions.get(position).user.getUserimageURL().isEmpty()) {
//holder.userimageprog.setVisibility(View.VISIBLE);
holder.imageView.setImageUrl(Profile_Fragment.BASE_URL + Questions.get(position).user.getUserimageURL(), _ImageLoader);
}
} else{
// I should use else statement as well
}
I tried to use viewpager and listview fragment in it with volley request.
When I first run program, I can see logs that I recieved data from api for both 1st and 2nd page. In that case 1st page shows blank page.
When I swipe to 2nd page I can see page with correct data if volley request came. In the same time I recieved 3rd page data from api(Because viewpager crates an instance of 3rd page). But when I click on item in 2nd page I get "The content of the adapter has changed but ListView did not receive a notification."
If I don't click on item in 2nd page and swipe to 3rd, I can see 3rd page with correct data and when I click on item it shows correct activity.
Invoking notifyDataSetChanged(); when I get response from api and tried setOffscreenPageLimit(0); to reload every page but nothing changes.
Here is my Adapters, Fragment and ServiceHandler classes.
MovieListAdapter
public class MovieListAdapter extends BaseAdapter {
private LayoutInflater l_Inflater;
private static List<MovieDetailModel> itemDetailsList;
private RequestQueue queue;
private ViewHolder holder;
//Constructor
public MovieListAdapter(Context context, List<MovieDetailModel> results) {
itemDetailsList = results;
l_Inflater = LayoutInflater.from(context);
queue = VolleySingleton.getInstance().getRequestQueue();
}
#Override
public int getCount() {
return itemDetailsList.size();
}
#Override
public Object getItem(int i) {
return itemDetailsList.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
//Holder pattern -> If new view required, create item for list
if (view == null) {
view = l_Inflater.inflate(R.layout.item_movie, null);
initializeHolder(view);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
setHolderItems(itemDetailsList, position);
return view;
}
static class ViewHolder {
TextView txt_title;
TextView txt_synopsis;
NetworkImageView itemImage;
}
private void initializeHolder(View view) {
holder = new ViewHolder();
holder.txt_title = (TextView) view.findViewById(R.id.title);
holder.txt_synopsis = (TextView) view.findViewById(R.id.synopsis);
holder.itemImage = (NetworkImageView) view.findViewById(R.id.list_image);
}
private void setHolderItems(List<MovieDetailModel> movieDetailModels, int position) {
holder.txt_title.setText(movieDetailModels.get(position).getTitle());
holder.txt_synopsis.setText(movieDetailModels.get(position).getSynopsis());
holder.itemImage.setImageUrl(movieDetailModels.get(position).getPosters().getThumbnail(), VolleySingleton.getInstance().getImageLoader());
}
}
TabsPagerAdapter
public class TabsPagerAdapter extends FragmentStatePagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
return MovieListFragment.newInstance(index);
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return Constants.TAB_COUNT;
}
}
MovieListFragment
public class MovieListFragment extends Fragment {
List<MovieDetailModel> movieDetailModelList;
public static MovieListAdapter movieListAdapter;
private int viewPagerPage;
OnMovieSelected movieItemClickListener;
public static MovieListFragment newInstance(int tabNumver){
MovieListFragment fragment = new MovieListFragment();
Bundle args = new Bundle();
args.putInt(Constants.ARG_TAB_ID,tabNumver);
fragment.setArguments(args);
return fragment;
}
public MovieListFragment(){
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
movieItemClickListener = (OnMovieSelected) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement onMovieSelected");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
viewPagerPage = getArguments().getInt(Constants.ARG_TAB_ID);
if (Constants.LOGS_ACTIVE) {
Log.d("TAB_ID", viewPagerPage + "");
}
View rootView = inflater.inflate(R.layout.fragment_movie_list, container, false);
ListView moviesListView = (ListView) rootView.findViewById(R.id.listview_movie_list);
setListView(moviesListView);
return rootView;
}
public List<MovieDetailModel> getSelectedMovieList(int tabId) {
switch (tabId) {
case 0:
return ServiceHandler.makeStringVolleyReq(Constants.BOX_OFFICE_LINK, getActivity());
case 1:
return ServiceHandler.makeStringVolleyReq(Constants.TOP_RENTALS_LINK, getActivity());
case 2:
return ServiceHandler.makeStringVolleyReq(Constants.UPCOMING_LINK, getActivity());
default:
return null;
}
}
private void setListView(ListView listView) {
movieDetailModelList = getSelectedMovieList(viewPagerPage);
movieListAdapter = new MovieListAdapter(getActivity(), movieDetailModelList);
listView.setAdapter(movieListAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
movieItemClickListener.onMovieSelected(movieDetailModelList.get(i));
Intent intent = new Intent(getActivity(), ActMovieDetails.class);
intent.putExtra(Constants.TAG_MOVIE, movieDetailModelList.get(i));
startActivity(intent);
} else {
if (Constants.LOGS_ACTIVE) {
Log.d("ORIETNTATION", "LANDSCAPE BUTTON");
}
movieItemClickListener.onMovieSelected(movieDetailModelList.get(i));
}
}
});
}
//For Callbacks
public interface OnMovieSelected {
public void onMovieSelected(MovieDetailModel movieDetailModel);
}
}
ServiceHandler
public static List<MovieDetailModel> makeStringVolleyReq(String url, final Context context) {
RequestQueue queue = VolleySingleton.getInstance().getRequestQueue();
ImageLoader mImageLoader;
final List<MovieDetailModel> movieList = new ArrayList<MovieDetailModel>();
StringRequest stringRequest = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// we got the response, now our job is to handle it
if(Constants.LOGS_ACTIVE) {
Log.d("JSON STRING: ", response);
}
movieList.addAll(JSONHandler.convertJSONArrayString2MoviesDetailModels(response));
if(Constants.LOGS_ACTIVE) {
for (int i = 0; i < movieList.size(); i++) {
Log.d("MOVIE", movieList.get(i).getTitle());
}
}
//ASK: How to set non-static?
MovieListFragment.movieListAdapter.notifyDataSetChanged();
if(SearchResultsActivity.searchResultsMovieListAdapter!=null){
SearchResultsActivity.searchResultsMovieListAdapter.notifyDataSetChanged();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//something happened, treat the error.
}
});
queue.add(stringRequest);
return movieList;
}
You are trying to update listView from different thread.
You should call notifyDataSetChanged() in the UI thread to resolve this.
Android basics: running code in the UI thread
My problem was static itemDetailsList in MovieListAdapter.
I haven't noticed that and tried everything.
Thanks for replies.