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.