0
Studying the MVP standard, I refactored an activity that lists the product data, just a simple list more that I do the data filtering, the information comes from the internal database and the filtering was done in the adapter list.
I believe I was able to apply the concept until the time came to refactoring the filtering so the question came to me? because it is a filtering of the data in the list I should implement the filtering in presenter? in the Model?
The Adapter I haven’t refactored yet that’s where the questions arose, and he has logic that is the filter itself is a logic so can not stay in the adapatador so where would be this logic someone can help me as I said I reviewed everything and I believe that to meet the standard just missing this.
follows the codes
interface ListaProdutosMVP {
interface View {
void atualizaLista();
void showToastError(String mensagem);
void showToastInfo(String mensagem);
void showToastWarning(String mensagem);
void showToastSuccess(String mensagem);
}
interface Presenter {
void recuperarProdutos();
void atualizaLista(ArrayList<Produto> produtos);
ArrayList<Produto> getProdutos();
Context getContext();
}
interface Model {
void recuperarProdutos();
}
Implementation of the Model
class ProdutoModel implements ListaProdutosMVP.Model {
private DAOProduto dao ;
private ListaProdutosMVP.Presenter presenter;
public ProdutoModel(ListaProdutosMVP.Presenter presenter) {
this.presenter = presenter;
this.dao = new DAOProduto(presenter.getContext()) ;
}
public Produto BuscaporId(int Id) { return dao.buscarPorId(Id); }
public List<Produto> buscarTodos() {
return dao.buscarTodos();
}
@Override
public void recuperarProdutos() {
ArrayList<Produto> lista = (ArrayList<Produto>) dao.getListaOrdenada();
presenter.atualizaLista( lista );
}
}
Implementation of the presenter
class ListaProdutosPresenter implements ListaProdutosMVP.Presenter {
private ArrayList<Produto> produtos = new ArrayList<>();
private ListaProdutosMVP.Model model;
private ListaProdutosMVP.View view;
public ListaProdutosPresenter(ListaProdutosMVP.View view){
this.view = view;
this.model = new ProdutoModel(this);
}
@Override
public void recuperarProdutos() {
model.recuperarProdutos();
}
@Override
public void atualizaLista(ArrayList<Produto> lista) {
produtos.clear();
produtos.addAll(lista);
view.atualizaLista();
}
@Override
public ArrayList<Produto> getProdutos() {
return produtos;
}
@Override
public Context getContext() {
return (Context) view;
}
}
Implementation of the View ( Activity )
class ListaProdutosActivity extends AppCompatActivity
implements ListaProdutosMVP.View {
private static final String TAG = "ListaProdutos";
private RecyclerView recyclerView;
private ProdutosAdapter adapter;
private ListaProdutosMVP.Presenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lista_produtos);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Log.i(TAG, "onCreate()");
if(presenter == null){
presenter = new ListaProdutosPresenter(this);
}
presenter.recuperarProdutos();
adapter = new ProdutosAdapter(this, presenter.getProdutos());
recyclerView = (RecyclerView) findViewById(R.id.rv_lista);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new
LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home){
finish();
}
return true;
}
@Override
public void atualizaLista() {
adapter.notifyDataSetChanged();
}
and finally Adapter and in it I started filtering the data and realized that this is logical so I must change this logic to the presenter or model?
class ProdutosAdapter extends
RecyclerView.Adapter<ProdutosAdapter.MyViewHolder>
implements Filterable {
private ListaProdutosActivity activity;
private ArrayList<Produto> items;
private ArrayList<Produto> mFilteredList;
public ProdutosAdapter(ListaProdutosActivity activity, ArrayList<Produto> items) {
this.activity = activity;
this.items = items;
this.mFilteredList = items;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater
.from(viewGroup.getContext())
.inflate(R.layout.model_produto_item, viewGroup, false);
return new MyViewHolder(v);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.setDados(mFilteredList.get(position));
}
@Override
public int getItemCount() {
return mFilteredList.size();
}
// Lógica
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
mFilteredList = items;
} else {
ArrayList<Produto> filteredList = new ArrayList<>();
for (Produto p : items) {
if (p.getNome().toLowerCase().contains(charString) ||
p.getEan_13().toLowerCase().contains(charString)
|| p.getDescricao().toLowerCase().contains(charString)) {
filteredList.add(p);
}
}
mFilteredList = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = mFilteredList;
return filterResults;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
mFilteredList = (ArrayList<Produto>) filterResults.values;
notifyDataSetChanged();
}
};
}
class MyViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
public TextView txtNome;
public TextView txtValor;
public TextView txtStatus;
public MyViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
txtNome = (TextView)itemView.findViewById(R.id.txtNome);
txtValor = (TextView)itemView.findViewById(R.id.txtValor);
txtStatus = (TextView)itemView.findViewById(R.id.txtStatus);
}
@Override
public void onClick(View v) {
Produto p = mFilteredList.get(getAdapterPosition());
activity.selectItem(p);
}
public void setDados(Produto produto) {
txtNome.setText(produto.getNome());
txtValor.setText( LetrasUtils.monetarioMask(produto.getValor()));
txtStatus.setText("Ativo: " + produto.getAtivo());
}
}
}
Simply put, the filter has to be done in the template, and you must pass it the query or any other information it needs to filter. The presenter is only the bridge, because the responsibility to retrieve the information is the model, and nothing fairer than being responsible for filtering.
– Wakim
Hello Wakim thanks for the return, my dear plus the model when the activity started he has already provided in full the records obtained from the bank, by Adapter the recyclerview has its list, the filtering ( handles data without a shadow of a doubt ) but only filters the elements of the list, list this that I put in the presenter so I get the doubt if I could not continue this step in the presenter.
– Robson
Assuming your model is simple, all right, it’s valid. But in real cases, you can have a Model that consumes data from an API or a local bank, or even both. Filtering in presenter might not be a good choice, it all depends on the context.
– Wakim
I am actually getting the list for the Sqlite Adapter (Local) this is what the Model does to get the list, and passes it to the presenter where I have a private instance Arraylist<Product> products, I do not intend to do a new search in the bank when doing a filtering (Search), if yes I would again request the template for a new list.
– Robson
Have the filtering in Presenter still go (although I think the Model should provide the filtered data) now the Model has a reference to the Presenter(
public ProdutoModel(ListaProdutosMVP.Presenter presenter)
) is that not.– ramaral
Hello ramaral good morning, yes the presenter can have a reference to the view public Listingssresenter(Listproductsmvp.View), and the model can not have reference to the Presenter? Why can you explain or suggest? , in this way I believe I was able to implement the standard there is bidirectional communication between the view and presenter, presenter and model
– Robson
This is imposed by the standard: Model <- Presenter <-> View. Presenter "knows" the Model and View, View "knows" the Presenter. The Model has no knowledge of the other two. See this post.
– ramaral
Check out these https://guides.codepath.com/android/Architecture-of-Android-Apps#migrating-to-clean-Architecture, and this other one http://konmik.com/post/introduction_to_model_view_presenter_on_android/ and even more this other one http://thefinestartist.com/android/mvp-pattern
– Robson
and if you look at the post you told me it still has part 2 and 3 (you read it), in part 2 we can see public Mainmodel(Mainmvp.Requiredpresenterops mPresenter) I saw no problems in how I implemented the pattern.
– Robson
OK,
MainMVP.RequiredPresenterOps
is a interface is not the Presenter. I hadn’t noticed that you were also using an interface.– ramaral