Как реализовать Fragment.onAttach() в адаптере (RecyclerView.Adapter)

207
21 сентября 2017, 14:31

Разрабатывается приложение, в котором используются фрагменты. Пытаюсь реализовать смену фрагмента по нажатию на любой item в recyclerView. Обработка нажатия происходит в адаптере.

TimeReportAdapter.java

public class TimeReportAdapter extends RecyclerView.Adapter<ViewHolder> {
public OnTimeReportAdapterActionListener mTimeReportAdapterCallBack;

public interface OnTimeReportAdapterActionListener {
    void onMinuteReportAction();
}
private Context context;
private List<TimeReport> mReportList = Collections.emptyList();
private SharedPreferences mSettings;
private static final String APP_PREFERENCES = "myValues";
private static final String APP_PREFERENCES_DATE = "date";
private Intent mIntent;
public TimeReportAdapter(Context context, List<TimeReport> reportList) {
    this.context = context;
    this.mReportList = reportList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
    final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_time_report, parent, false);
    return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    final TimeReport report = mReportList.get(position);
    holder.tv_time.setText(report.getmTime());
    holder.tv_count.setText(String.valueOf(report.getmCount()));
    // обработка нажатия по item
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // запись в SharedPreferences
            mSettings = context.getApplicationContext().getSharedPreferences(APP_PREFERENCES, Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = mSettings.edit();
            editor.putString(APP_PREFERENCES_DATE, report.getmTime());
            editor.apply();
            Log.d("savedSharedPreferences", APP_PREFERENCES_DATE +" "+ report.getmTime());
            // вызов смены фрагмента
            mTimeReportAdapterCallBack.onMinuteReportAction();
        }
    });
}
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mTimeReportAdapterCallBack = (OnTimeReportAdapterActionListener) activity;
    } catch (ClassCastException e) {
        FirebaseCrash.report(e);
        throw new ClassCastException(activity.toString()
                + " must implement OnTimeReportAdapterActionListener");
    }
}
@Override
public int getItemCount() {
    return mReportList.size();
}}

TimeReportFragment.java

public class TimeReportFragment extends Fragment {
private static View mRootView = null;
private ImageButton mRefreshBtn = null; // кнопка "обновить"
private ArrayList<TimeReport> mTimeReports = null;
private TimeReportAdapter mTimeReportAdapter = null;
private RecyclerView mRecycler = null;
private ProgressBar mProgressBar = null; // анимация загрузки
private LinearLayout mHeader = null;
private View mLine = null;
public Adapter adapter;
public TimeReportFragment() {
    // Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    mRootView = inflater.inflate(R.layout.fragment_time_report, container, false);
    initializeViews();
    doSendTimeReportRequest(); // отправка запроса, получение, парсинг json, установка в recyclerView
    mRefreshBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            doSendTimeReportRequest();
        }
    });
    return mRootView;
}
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mTimeReportAdapter.setInterface((TimeReportAdapter.OnTimeReportAdapterActionListener) activity);
        //mTimeReportFragmentCallBack = (TimeReportFragment.OnTimeReportFragmentActionListener) activity;
    } catch (ClassCastException e) {
        FirebaseCrash.report(e);
        throw new ClassCastException(activity.toString()
                + " must implement OnTimeReportFragmentActionListener");
    }
}

TimeReportAdapter.java (обновленный)

public class TimeReportAdapter extends RecyclerView.Adapter<ViewHolder> {
public OnTimeReportAdapterActionListener mTimeReportAdapterCallBack;
public interface OnTimeReportAdapterActionListener {
    void onMinuteReportAction();
}
private Fragment fragment;
private MainActivity mainActivity;
private Context context;
private List<TimeReport> mReportList = Collections.emptyList();
private SharedPreferences mSettings;
private static final String APP_PREFERENCES = "myValues";
private static final String APP_PREFERENCES_DATE = "date";
public TimeReportAdapter(Context context, List<TimeReport> reportList) {
    this.context = context;
    this.mReportList = reportList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
    final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_time_report, parent, false);
    return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    final TimeReport report = mReportList.get(position);
    holder.tv_time.setText(report.getmTime());
    holder.tv_count.setText(String.valueOf(report.getmCount()));
    // обработка нажатия по item
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // запись в SharedPreferences
            mSettings = context.getApplicationContext().getSharedPreferences(APP_PREFERENCES, Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = mSettings.edit();
            editor.putString(APP_PREFERENCES_DATE, report.getmTime());
            editor.apply();
            Log.d("savedSharedPreferences", APP_PREFERENCES_DATE +" "+ report.getmTime());
            // вызов смены фрагмента
            mTimeReportAdapterCallBack.onMinuteReportAction();
            //mTimeReportAdapterCallBack.onMinuteReportAction();
        }
    });
}
public void setInterface(OnTimeReportAdapterActionListener myInterface) {
    this.mTimeReportAdapterCallBack = myInterface;
}
@Override
public int getItemCount() {
    return mReportList.size();
}}

Конструкция приложения такова, что смена всех фрагментов происходит в MainActivity с которым взаимодействуют фрагменты через интерфейсы. Приложение разрабатываю не с нуля, поэтому структуру менять не могу.

Чтобы все заработало необходимо реализовать метод onAttach(). Но для этого нужно наследоваться от Fragment, а не RecyclerView.Adapter. Как быть?

Вопрос: как реализовать метод onAttach(), или как по другому реализовать вызов mTimeReportAdapterCallBack.onMinuteReportAction() чтобы он не был null?

Answer 1

В адаптере есть следующий метод, переопределите его и получите context из recyclerview, context и есть ваше activity которое можно преобразовать в интерфейс

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        context = recyclerView.getContext();
}
Answer 2

onAttach - это метод фрагмента. Реализовать его в адаптере невозможно.

Вам надо действовать иначе. Судя по приведённому коду, вам лучше всего сделать сеттер для вашего интерфейса и передавать его экземпляр из фрагмента в адаптер при вызове onAttach у фрагмента.

Примерно так:

public class Fr extends Fragment {
    Adapter adapter;
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        adapter.setInterface((OnTimeReportAdapterActionListener) activity);
    }
    public void onDetach() {
        super.onDetach();
        adapter.setInterface(null);
    }
}
public class Adapter extends RecyclerView.Adapter {
    public void setInterface(Interface myInterface) {
        this.myInterface = myInterface;
    }
}
READ ALSO
Immutable объект в Java

Immutable объект в Java

В java все объект могут быть mutable и immutableПонятно, что, например, строка является immutable

238
Java Bean Не инжектит бины

Java Bean Не инжектит бины

Здравствуйте! Второй день пытаюсь пофиксить проблемуВ проекте пытаюсь достать данные из базы, но вылетает NullPointerException

186
Java-Spring: Как выдавать JSON со связями?

Java-Spring: Как выдавать JSON со связями?

Всем доброго дня! Сервер написан на Java + Spring framework + PostgresqlМне нужно выдавать JSON такого вида:

171
Определение штата оффлайн

Определение штата оффлайн

Как определить штат по координатам, без запросов к google mapЖелательно оффлайн

130