RecyclerView,GridLayoutManager和动态Spans计数

时间:2015-02-20 23:53:40

标签: android android-asynctask android-recyclerview

我在recyclerview遇到了一个奇怪的错误。我动态设置和调整跨度以适应从AsyncTask下载的信息。

有时它无法正常显示。它似乎显示在屏幕上。!

enter image description here

enter image description here

然后在重新加载一次或多次后,它会正确显示。 它似乎走出了屏幕,但我无法弄清楚原因。

这是我的适配器:

   public class ScheduleAdapter extends RecyclerView.Adapter<ScheduleAdapter.ViewHolder> {

    private List<Schedule> mDataset;
    /**
     * First parameter is the position in the dataset
     * The value returned is the number of schedules to display
     */
    private TreeMap<Integer, Integer> schedulesToDisplay;
    private int maxSpans;

    private static final String TAG="LINE_ADATER";

    // Provide a suitable constructor (depends on the kind of dataset)
    public ScheduleAdapter() {
        mDataset = new ArrayList<Schedule>();
        schedulesToDisplay = new TreeMap<Integer, Integer>();
    }

    // Create new views (invoked by the layout manager)
    @Override
    public ScheduleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_schedule, parent, false);
        // set the view's size, margins, paddings and layout parameters
        ViewHolder vh = new ViewHolder((LinearLayout) v);
        return vh;
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        Log.d(""+position, "BINDVIEW");
        holder.setItem(mDataset.get(position));
        Schedule s = mDataset.get(position);
        holder.time.setText(s.toString());
    }

    public void add(Schedule item) {
        Integer nbHour = schedulesToDisplay.get(item.hour);
        int position = mDataset.size();
        if(nbHour == null){
            schedulesToDisplay.put(item.hour, 1);
            Log.d(item.toString()+" : 1 span ("+position+")", TAG);
        }
        else{
            nbHour++;
            schedulesToDisplay.put(item.hour, nbHour);
            Log.d(item.toString()+ " : " + nbHour +" spans ("+position+")", TAG);
            if(nbHour > maxSpans){
                maxSpans = nbHour;
            }
        }
        mDataset.add(position, item);
        notifyItemInserted(position);
    }

    public List<Schedule> getDataSet(){
        return mDataset;
    }

    public int getSchedulesToDisplay(int position, GridLayoutManager layoutManager){
        Integer nbHour = schedulesToDisplay.get(mDataset.get(position).hour);
        if(nbHour==null){
            return 0;
        }
        int nbHourInt = nbHour.intValue();
        if( maxSpans%nbHourInt != 0){ // Si la nouvelle ligne n'est pas un multiple de la précédente
            maxSpans = (maxSpans*nbHourInt)/ MathsUtils.pgcd(maxSpans, nbHourInt);
            Log.d("New Max Span "+maxSpans, TAG);
        }
        layoutManager.setSpanCount(maxSpans);
        layoutManager.requestLayout();
        layoutManager.getSpanSizeLookup().invalidateSpanIndexCache();

        Log.d("Span count "+layoutManager.getSpanCount(), TAG);
        Log.d("Heure "+mDataset.get(position).hour+" ("+nbHourInt+") : "+(maxSpans/nbHourInt)+" spans", TAG+" SPAN");
        return (maxSpans/nbHourInt);
    }

    public void removeAll() {
        mDataset.clear();
        schedulesToDisplay.clear();
        maxSpans = 1;
        notifyDataSetChanged();
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder{
        // each data item is just a string in this case
        TextView time;
        Schedule scheduleItem;

        public ViewHolder(LinearLayout lyt_main) {
            super(lyt_main);
            time = (TextView) lyt_main.findViewById(R.id.time);
        }

        public void setItem(Schedule item) {
            scheduleItem = item;
        }
    }
}

每次下载新数据之前,都会从活动中调用removeAll()方法。

1 个答案:

答案 0 :(得分:1)

其实我解决了这个问题。我注意到只在notifyItemInserted之后调用了setSpanSizeLookup方法。我必须把调整大小的方法放在。

之后
public void add(Schedule item) {
    Integer nbHour = schedulesToDisplay.get(item.hour);
    int position = mDataset.size();
    if(nbHour == null){
        schedulesToDisplay.put(item.hour, 1);
        Log.d(item.toString()+" : 1 span ("+position+")", TAG);
    }
    else{
        nbHour++;
        schedulesToDisplay.put(item.hour, nbHour);
        Log.d(item.toString()+ " : " + nbHour +" spans ("+position+")", TAG);
        if(nbHour > maxSpans){
            maxSpans = nbHour;
        }
    }
    mDataset.add(position, item);
    notifyItemInserted(position);

    layoutManager.setSpanCount(maxSpans);
    layoutManager.requestLayout();
}