<commit_before>
package com.airbnb.epoxy;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager.SpanSizeLookup;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * Allows you to easily combine different view types in the same adapter, and handles view holder
 * creation, binding, and ids for you. Subclasses just need to add their desired {@link EpoxyModel}
 * objects and the rest is done automatically.
 * <p/>
 * {@link android.support.v7.widget.RecyclerView.Adapter#setHasStableIds(boolean)} is set to true by
 * default, since {@link EpoxyModel} makes it easy to support unique ids. If you don't want to
 * support this then disable it in your base class (not recommended).
 */
@SuppressWarnings("WeakerAccess")
public abstract class EpoxyAdapter extends RecyclerView.Adapter<EpoxyViewHolder> {
  private static final String SAVED_STATE_ARG_VIEW_HOLDERS = "saved_state_view_holders";

  /**
   * Subclasses should modify this list as necessary with the models they want to show. Subclasses
   * are responsible for notifying data changes whenever this list is changed.
   */
  protected final List<EpoxyModel<?>> models = new ArrayList<>();
  private int spanCount = 1;
  private final HiddenEpoxyModel hiddenModel = new HiddenEpoxyModel();
  /**
   * Keeps track of view holders that are currently bound so we can save their state in {@link
   * #onSaveInstanceState(Bundle)}.
   */
  private final BoundViewHolders boundViewHolders = new BoundViewHolders();
  private ViewHolderState viewHolderState = new ViewHolderState();
  private DiffHelper diffHelper;

  private final SpanSizeLookup spanSizeLookup = new SpanSizeLookup() {

    @Override
    public int getSpanSize(int position) {
      try {
        return getModelForPosition(position).getSpanSize(spanCount, position, getItemCount());
      } catch (IndexOutOfBoundsException e) {
        // There seems to be a GridLayoutManager bug where when the user is in accessibility mode
        // it incorrectly uses an outdated view position
        // when calling this method. This crashes when a view is animating out, when it is
        // removed from the adapter but technically still added
        // to the layout. We've posted a bug report and hopefully can update when the support
        // library fixes this
        // TODO: (eli_hart 8/23/16) Figure out if this has been fixed in new support library
        return 1;
      }
    }
  };

  public EpoxyAdapter() {
    // Defaults to stable ids since view models generate unique ids. Set this to false in the
    // subclass if you don't want to support it
    setHasStableIds(true);
    spanSizeLookup.setSpanIndexCacheEnabled(true);
  }

  /**
   * Enables support for automatically notifying model changes via {@link #notifyModelsChanged()}.
   * If used, this should be called in the constructor, before any models are changed.
   *
   * @see #notifyModelsChanged()
   */
  protected void enableDiffing() {
    if (diffHelper != null) {
      throw new IllegalStateException("Diffing was already enabled");
    }

    if (!models.isEmpty()) {
      throw new IllegalStateException("You must enable diffing before modifying models");
    }

    if (!hasStableIds()) {
      throw new IllegalStateException("You must have stable ids to use diffing");
    }

    diffHelper = new DiffHelper(this);
  }

  /**
   * Intelligently notify item changes by comparing the current {@link #models} list against the
   * previous so you don't have to micromanage notification calls yourself. This may be
   * prohibitively slow for large model lists (in the hundreds), in which case consider doing
   * notification calls yourself. If you use this, all your view models must implement {@link
   * EpoxyModel#hashCode()} to completely identify their state, so that changes to a model's content
   * can be detected. Before using this you must enable it with {@link #enableDiffing()}, since
   * keeping track of the model state adds extra computation time to all other data change
   * notifications.
   *
   * @see #enableDiffing()
   */

  protected void notifyModelsChanged() {
    if (diffHelper == null) {
      throw new IllegalStateException("You must enable diffing before notifying models changed");
    }

    diffHelper.notifyModelChanges();
  }

  @Override
  public int getItemCount() {
    return models.size();
  }

  public boolean isEmpty() {
    return models.isEmpty();
  }

  @Override
  public EpoxyViewHolder onCreateViewHolder(ViewGroup parent, int layoutRes) {
    return new EpoxyViewHolder(parent, layoutRes);
  }

  @Override
  public void onBindViewHolder(EpoxyViewHolder holder, int position) {
    onBindViewHolder(holder, position, Collections.emptyList());
  }

  @Override
  public void onBindViewHolder(EpoxyViewHolder holder, int position, List<Object> payloads) {
    // A ViewHolder can be bound again even it is already bound and showing, like when it is on
    // screen and is changed. In this case we need
    // to carry the state of the previous view over to the new view. This may not be necessary if
    // the viewholder is reused (see RecyclerView.ItemAnimator#canReuseUpdatedViewHolder)
    // but we don't rely on that to be safe and to simplify
    EpoxyViewHolder boundViewHolder = boundViewHolders.get(holder);
    if (boundViewHolder != null) {
      viewHolderState.save(boundViewHolder);
    }

    EpoxyModel<?> modelToShow = getModelForPosition(position);
    holder.bind(modelToShow, payloads);

    viewHolderState.restore(holder);
    boundViewHolders.put(holder);

    onModelBound(holder, modelToShow);
  }

  /**
   * Called immediately after a model is bound to a view holder. Subclasses can override this if
   * they want alerts on when a model is bound.
   */
  protected void onModelBound(EpoxyViewHolder holder, EpoxyModel<?> model) {

  }

  protected BoundViewHolders getBoundViewHolders() {
    return boundViewHolders;
  }

  @Override
  public int getItemViewType(int position) {
    return getModelForPosition(position).getLayout();
  }
<commit_msg>Add position param to onModelBound method in EpoxyAdapter<commit_after>
package com.airbnb.epoxy;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager.SpanSizeLookup;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * Allows you to easily combine different view types in the same adapter, and handles view holder
 * creation, binding, and ids for you. Subclasses just need to add their desired {@link EpoxyModel}
 * objects and the rest is done automatically.
 * <p/>
 * {@link android.support.v7.widget.RecyclerView.Adapter#setHasStableIds(boolean)} is set to true by
 * default, since {@link EpoxyModel} makes it easy to support unique ids. If you don't want to
 * support this then disable it in your base class (not recommended).
 */
@SuppressWarnings("WeakerAccess")
public abstract class EpoxyAdapter extends RecyclerView.Adapter<EpoxyViewHolder> {
  private static final String SAVED_STATE_ARG_VIEW_HOLDERS = "saved_state_view_holders";

  /**
   * Subclasses should modify this list as necessary with the models they want to show. Subclasses
   * are responsible for notifying data changes whenever this list is changed.
   */
  protected final List<EpoxyModel<?>> models = new ArrayList<>();
  private int spanCount = 1;
  private final HiddenEpoxyModel hiddenModel = new HiddenEpoxyModel();
  /**
   * Keeps track of view holders that are currently bound so we can save their state in {@link
   * #onSaveInstanceState(Bundle)}.
   */
  private final BoundViewHolders boundViewHolders = new BoundViewHolders();
  private ViewHolderState viewHolderState = new ViewHolderState();
  private DiffHelper diffHelper;

  private final SpanSizeLookup spanSizeLookup = new SpanSizeLookup() {

    @Override
    public int getSpanSize(int position) {
      try {
        return getModelForPosition(position).getSpanSize(spanCount, position, getItemCount());
      } catch (IndexOutOfBoundsException e) {
        // There seems to be a GridLayoutManager bug where when the user is in accessibility mode
        // it incorrectly uses an outdated view position
        // when calling this method. This crashes when a view is animating out, when it is
        // removed from the adapter but technically still added
        // to the layout. We've posted a bug report and hopefully can update when the support
        // library fixes this
        // TODO: (eli_hart 8/23/16) Figure out if this has been fixed in new support library
        return 1;
      }
    }
  };

  public EpoxyAdapter() {
    // Defaults to stable ids since view models generate unique ids. Set this to false in the
    // subclass if you don't want to support it
    setHasStableIds(true);
    spanSizeLookup.setSpanIndexCacheEnabled(true);
  }

  /**
   * Enables support for automatically notifying model changes via {@link #notifyModelsChanged()}.
   * If used, this should be called in the constructor, before any models are changed.
   *
   * @see #notifyModelsChanged()
   */
  protected void enableDiffing() {
    if (diffHelper != null) {
      throw new IllegalStateException("Diffing was already enabled");
    }

    if (!models.isEmpty()) {
      throw new IllegalStateException("You must enable diffing before modifying models");
    }

    if (!hasStableIds()) {
      throw new IllegalStateException("You must have stable ids to use diffing");
    }

    diffHelper = new DiffHelper(this);
  }

  /**
   * Intelligently notify item changes by comparing the current {@link #models} list against the
   * previous so you don't have to micromanage notification calls yourself. This may be
   * prohibitively slow for large model lists (in the hundreds), in which case consider doing
   * notification calls yourself. If you use this, all your view models must implement {@link
   * EpoxyModel#hashCode()} to completely identify their state, so that changes to a model's content
   * can be detected. Before using this you must enable it with {@link #enableDiffing()}, since
   * keeping track of the model state adds extra computation time to all other data change
   * notifications.
   *
   * @see #enableDiffing()
   */

  protected void notifyModelsChanged() {
    if (diffHelper == null) {
      throw new IllegalStateException("You must enable diffing before notifying models changed");
    }

    diffHelper.notifyModelChanges();
  }

  @Override
  public int getItemCount() {
    return models.size();
  }

  public boolean isEmpty() {
    return models.isEmpty();
  }

  @Override
  public EpoxyViewHolder onCreateViewHolder(ViewGroup parent, int layoutRes) {
    return new EpoxyViewHolder(parent, layoutRes);
  }

  @Override
  public void onBindViewHolder(EpoxyViewHolder holder, int position) {
    onBindViewHolder(holder, position, Collections.emptyList());
  }

  @Override
  public void onBindViewHolder(EpoxyViewHolder holder, int position, List<Object> payloads) {
    // A ViewHolder can be bound again even it is already bound and showing, like when it is on
    // screen and is changed. In this case we need
    // to carry the state of the previous view over to the new view. This may not be necessary if
    // the viewholder is reused (see RecyclerView.ItemAnimator#canReuseUpdatedViewHolder)
    // but we don't rely on that to be safe and to simplify
    EpoxyViewHolder boundViewHolder = boundViewHolders.get(holder);
    if (boundViewHolder != null) {
      viewHolderState.save(boundViewHolder);
    }

    EpoxyModel<?> modelToShow = getModelForPosition(position);
    holder.bind(modelToShow, payloads);

    viewHolderState.restore(holder);
    boundViewHolders.put(holder);

    onModelBound(holder, modelToShow, position);
  }

  /**
   * Called immediately after a model is bound to a view holder. Subclasses can override this if
   * they want alerts on when a model is bound.
   */
  protected void onModelBound(EpoxyViewHolder holder, EpoxyModel<?> model, int position) {

  }

  protected BoundViewHolders getBoundViewHolders() {
    return boundViewHolders;
  }

  @Override
  public int getItemViewType(int position) {
    return getModelForPosition(position).getLayout();
  }

{'fraction_non_alphanumeric': 0.07748375851687529, 'fraction_numerical': 0.001584534938995405, 'mean_word_length': 3.7401426962072852, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5324260', 'n_tokens_mistral': 3437, 'n_tokens_neox': 3302, 'n_words': 1316}