ViewPager片段未同步更新?

时间:2016-02-01 11:57:43

标签: android android-fragments android-viewpager android-recyclerview fragmentstatepageradapter

我有一个 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页。

我尝试了所有可能的解决方案。

任何建议都会受到赞赏。

1 个答案:

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

工作安静但服务于目的:)