Где я должен отпереть ButterKnife 8.x.x в ViewHolder?

У меня есть класс RecycleView.ViewHolder, который использует аннотации ButterKnife.

Должен ли мой код unbind() в этом классе ViewHolder тоже?

public class AView extends RecyclerView.ViewHolder
{
    @BindView(R.id.a_text_view) TextView aText;

    public AView(final View view)
    {
        super(view);
        ButterKnife.bind(this, view); // It returns an Unbinder, but where should I call its unbind()?
    }
}

Документы (http://jakewharton.github.io/butterknife/) не говорят об этой проблеме.

Ответы

Ответ 1

По словам Джейка Уортона, автор Butterknife, unbind() требуется только для Fragments. См. Этот комментарий к трекеру вопросов:

https://github.com/JakeWharton/butterknife/issues/879

Q: В RecyclerView, как мы отвязаем ViewHolder?

A: Вам не нужно. Только Fragments нужно в onDestroyView().

Причина в том, что

[ViewHolders] не ожидают связанного представления. A Fragment.

Другими словами, поскольку a Fragment может продолжать существовать после уничтожения его Views, вам нужно вызвать .unbind() из Fragment, чтобы освободить ссылку на Views (и разрешить связанный память будет восстановлена).

При ViewHolder жизненный цикл держателя совпадает с Views. Другими словами, ViewHolder и его Views уничтожаются одновременно, поэтому никогда не существует затяжной ссылки от одной к другой, которую нужно вручную очистить.

Ответ 2

Здесь объяснение WHEN и WHY использовать метод unbind():

BINDING RESET

Фрагменты имеют иной жизненный цикл представления, чем действия. когда связывание фрагмента в onCreateView, установите представления в null в onDestroyView. Butter Knife возвращает экземпляр Unbinder, когда вы вызовите bind, чтобы сделать это для вас. Вызовите его метод unbind в соответствующий обратный вызов жизненного цикла.

public class FancyFragment extends Fragment {
  @BindView(R.id.button1) Button button1;
  @BindView(R.id.button2) Button button2;
  private Unbinder unbinder;

  @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fancy_fragment, container, false);
    unbinder = ButterKnife.bind(this, view);
    // TODO Use fields...
    return view;
  }

  @Override public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
  }
}

От: http://jakewharton.github.io/butterknife/#reset

поэтому вам совсем не нужно unbind любого вида из ViewHolder.

Надеюсь, что это поможет

Ответ 3

В документе есть пример, который демонстрирует, как использовать эту библиотеку в ViewHolder:

static class ViewHolder {
    @BindView(R.id.title) TextView name;
    @BindView(R.id.job_title) TextView jobTitle;

    public ViewHolder(View view) {
      ButterKnife.bind(this, view);
    }
  }

Таким образом, нет необходимости вызывать unbind для вашего ViewHolder.

Ответ 5

Просто используйте это:

@Override
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
    if (unbinder != null) {
        unbinder.unbind();
    }
}

Ответ 6

Джейквартон четко упомянул в своей документации

https://jakewharton.github.io/butterknife/

Unbind следует вызывать только для фрагментов и, что самое важное, вызывать его в onDestroyView вместо DestroyView.