我有一个 MainActivity ,它首先调用我的服务器并获得响应。然后,在第一次回复成功时,我正在启动 viewPager 。
下面,调用代码来启动viewPager及其适配器,只有在第一次响应成功后才会调用它。
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));
}
这是我的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;
}
}
此处,在viewPager的 getItem()方法回调中,它为每个位置创建一个新片段,并检查所选位置的数据是否可用。如果是,那么第一个位置显然会有,因为它是在第一个响应成功后调用的,它会将数据传递给片段。
如果没有,它将向服务器发出新的api请求,以获取数据。 由于viewPager会提前缓存2个页面,因此它会发出2个请求并缓存数据。
在每个请求中,我正在使用数据更新 hashMap 。
这是我的片段,它始终针对每个位置启动。
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;
}
}
以下是我的recyclerViewAdapter,它是从片段中调用的。
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();
}
}
我的问题就在这里,即使请求是异步的,我想显示一个加载器,如果数据还没有来,那么数据上的viewPager片段来自服务器和hideLoading。
当我覆盖viewPager的 getItemPosition()并从那里返回 POSITION_NONE 时,它正常工作,但我不想这样做,因为它正在重新创建片段,并使我的应用程序变慢。
我尝试为每个片段设置TAG,并且 onPositionSelected()回调viewPager监听器,我尝试交换每个片段的recyclerView内容,但它不起作用。
令人惊讶的是,它会加载所有数据,如果继续滑动到其他页面并返回到第1页或第2页。
我尝试了所有可能的解决方案。
任何建议都会受到赞赏。
答案 0 :(得分:1)
这就是你保持结果的方式,你保持这是无关紧要的
private LinkedHashMap<String, List<Venue>> mVenueHashMap;
这就是你实例化片段的方式
ShowTimeFragment showTimeFragment = ShowTimeFragment.newInstance(stringDate);
如果我没有弄错,你还希望片段加载数据,如果我没有弄错,那么你应该在片段中执行以下操作
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
}
}
}
并且您的VenueResponse
类看起来像这样
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;
}
}
在您的活动中,无论您何时收到网络响应,都会执行以下操作来保存和通知片段
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));
工作安静但服务于目的:)