Как оформить приложение в стиле mvp? Про mvp читал, не понятно как в эту систему впилить RecycleView c его адаптером.
Вот то что на данный момент есть: на github.
Денис Лобода, нет, неправильно. Презентер никогда не должен знать ничего про андроидовые вьюхи(ресайклер, его адаптер и тд), про контекст и так далее. У MVPView должен быть метод showItems(List), который дергает презентер и в котором элементы просечиваются в адаптер. Это и называется "ресайклер спрятан в реализации вью".
Денис Загаевский, я переписал презентер, теперь туда не передается вью.
У MVPView должен быть метод showItems(List), который дергает презентер и в котором элементы просечиваются в адаптер.
Я не пойму где этот метод будет вызываться, в адаптере?
Я правильно понял, что в адаптере не должно ничего хранится касательно модели? то есть в этом коде:
код адаптера
public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder>
{
private ArrayList<Crime> mCrimes;
private final ListAdapterCallback mListener;
public ListAdapter(ListAdapterCallback listener)
{
mCrimes = CrimeLab.get().getCrimes();
mListener = listener;
}
public Crime getItem(int position)
{
return mCrimes.get(position);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item,parent,false);
return new ViewHolder(view, mListener);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position)
{
holder.mTitle.setText(mCrimes.get(position).getTitle());
holder.mDate.setText(mCrimes.get(position).getDate().toString());
holder.mSolved.setChecked(mCrimes.get(position).isSolved());
}
@Override
public int getItemCount()
{
return mCrimes.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
private final ListAdapterCallback mListener;
TextView mTitle;
TextView mDate;
CheckBox mSolved;
public ViewHolder(View itemView, ListAdapterCallback listener)
{
super(itemView);
mListener = listener;
this.itemView.setOnClickListener(this);
mTitle = itemView.findViewById(R.id.crime_item_title);
mDate = itemView.findViewById(R.id.crime_item_date);
mSolved = itemView.findViewById(R.id.crime_item_solved);
}
@Override
public void onClick(View v)
{
mListener.onItemClick(getAdapterPosition());
}
}
}
нужно не хранить ArrayList а каждый раз кода необходимо обращаться к презентеру, что бы тот предоставил соответствующие данные? или я что то опять не так понял...
Денис Лобода, што.
Презентер получает данные и зовёт метод setItems у Вью. Вью вообще не знает про презентер (у Вью даже ссылки на него быть не должно, не то, что данные требовать).
Денис Лобода, метод setItems у Вью, что тут может быть непонятного? В интерфейсе и реализации View.
Про примеры - они какие-то стрёмные. Ссылок на контекст у презентера быть не должно. У Вью максимум ссылка на листенер, который реализует презентер. Активити и фрагменты - только точки входа, клей, если угодно.
Денис Загаевский, получается, вью содержит интерфейс презентера, а презентер интерфейс вью и модель. вью генерирует события (нажатие на кнопку, изменение текста в поле ввода и т.д.) вызывая методы интерфейса презентера, на которые презентер реагирует обработкой модели и вызовом методов интерфейса вью для отображения измененной информации. я правильно это понимаю?
получается в адаптере будет метод наподобие этого:
public void addAll(ArrayList<String> list)
{
mModel.clear();
for(String s : list)
{
mModel.add(s);
}
notifyDataSetChanged();
}
а во вью такой метод:
@Override
public void showList(ArrayList<String> list)
{
((ListAdapter)mRecyclerView.getAdapter()).addAll(list);
}
но остается не понятным, когда этот метод будет вызываться?
Да, что-то типа того и должно быть. Только проще сделать, чтобы презентер сразу отдавал список неких Item-ов, которые вью должна уметь отображать. Даже если сейчас надо отображать только строки - все равно лучше завернуть их в небольшие модельки, тогда, если понадобится отображать и другие данные, то все будет проще. Плюс, стоит использовать DiffUtil для изменения списка.
В смысле, когда он должен вызываться? Когда презентер сочтёт нужным(у него откуда-то появляются данные, чаще всего - асинхронно: из БД, сети, файл, любой i/o должен быть асинхронным), вот они пояились и он дернул у вью метод для их отображения.
если я в OnCreate у фрагмента сообщу презентеру об этом (вызову какой то метод init() у интерфейса презентера), и он в этот момент загрузит все данные необходимые для отображения в списке и вызовет showList, это будет правильно?