0

我有一個MainActivity它首先打電話給我的服務器並獲得響應。然後,在第一個響應的成功,我開始viewPagerViewPager片段不同步更新?

下面調用代碼來啓動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; 
    } 

} 

在這裏,上getItem()時viewPager的方法回調,它會爲每個位置,並檢查新的片段如果所選位置處的數據是可用的或沒有。如果是的話,這顯然會出現在第一個位置,因爲它是在第一個響應成功之後調用的,它會將數據傳遞給片段。

如果不是,它會向服務器發出一個新的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。

它的正常工作,當我重寫getItemPosition()viewPager的,並從那裏返回POSITION_NONE,但我不希望這樣做,因爲它重新創建片段,並讓我的應用程序緩慢。

我試着設置每個片段的標籤和onPositionSelected()回調的viewPager監聽器,我試着交換每個片段的recyclerView內容,但它沒有工作。

令人驚訝的是,它加載所有的數據,如果保持滑動到其他頁面並返回到第1頁或第2頁。

我嘗試了所有可能的解決方案。

任何形式的建議,將不勝感激。

+0

你確定這是你的RecyclerView適配器? –

+0

@MuchOverflow謝謝你的注意,我已經更新了我的問題。請看一看。 – Ritesh

+0

我會通過使用EventBus(例如Square的Otto)來緩解這個問題。最初我會用ProgressBar打開片段。然後我會檢查數據是否加載了特定的片段。如果是這樣,我會隱藏加載器並顯示數據。如果沒有,我將用EventBus註冊片段,並等待它加載數據後作出響應。 –

回答

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)); 

它是安靜一個工作,但服務於此目的:)

+0

謝謝你的答案..我嘗試了,如果我沒有錯,你的代碼中的「myResults」實際上就是「yourResults」。 – Ritesh

+0

謝謝你的注意。我已經確定它更清楚。 –

+0

歡迎您,當您顯示進度條時,我認爲應該在調用onCreateView()回調時啓動它。 – Ritesh