Model View Presenter Class Diagram

Model View Presenter (MVP) no Android, Parte 3

Na conclusão da série sobre Model View Presenter (MVP) no Android, vamos falar um pouco sobre como utilizar o framework disponível no GitHub para facilitar o processo de produção, além de discutir alguns gargalos que podem ficar no caminho daqueles que estão tentando implementar seus projetos utilizando MVP.

Utilizando o framework Model View Presenter

Este framework foi implementado sobre o conceito do Dr. Douglas C. Schmidt. O código segue princípios canónicos e não utiliza nenhuma library ou recurso que não seja standard do SDK Android. A maior vantagem desta abordagem é que o projeto que o utilize estará sempre em sincronia com o ambiente Android, não dependendo de atualizações de librarys. Como nem tudo são flores, existem algumas exigências que precisam ser atendidas para o funcionamento correto.

Interfaces de comunicação entre layers

Comece implementando as interfaces que permitem a comunicação entre os layers do Model View Presenter. Você precisará de quatro interfaces: RequiredViewOps ,  ProvidedPresenterOps ,  RequiredPresenterOps  e  ProvidedModelOps .

/**
     * Métodos obrigatórios em View, disponíveis para Presenter
     *      Presenter -> View
     */
    interface RequiredViewOps extends ActivityView {
    }


    /**
     * operações oferecidas ao layer View para comunicação com Presenter
     *      View -> Presenter
     */
    interface ProvidedPresenterOps extends PresenterOps<RequiredViewOps> {
    }

    /**
     * operações oferecidas pelo layer Presenter para comunicações com Model
     *      Model -> Presenter
     */
    interface RequiredPresenterOps {
    }

    /**
     * operações oferecidos pelo layer Model para comunicações com Presenter
     *      Presenter -> Model
     */
    interface ProvidedModelOps extends ModelOps<RequiredPresenterOps>{
    }

Caso utilize um Fragment como layer View, deverá também implementar outra interface, a RequiredActivityOps  que permite comunicação entre o layer Fragment e a Activity, caso exista a necessidade.

Implementando os layers Model, View e Presenter

Todos os layers possuem objetos abstratos para facilitar a implementação. Estas classes executam a maior parte do trabalho pesado, restando a suas super classes apenas iniciá-los.

Para Model extenda GenericModel<RequiredPresenterOps> implements ModelOps<RequiredPresenterOps>

public class MainModel extends GenericModel<MVP_MainActivity.RequiredPresenterOps>
        implements MVP_MainActivity.ProvidedModelOps {

    /**
     * Método que recupera referência ao layer PRESENTER
     * 1 - {@link super#onCreate(Object)} deve sempre deve ser chamado
     * @param presenterOps  interface com o Presenter
     */
    @Override
    public void onCreate(MVP_MainActivity.RequiredPresenterOps presenterOps) {
        super.onCreate(presenterOps);
    }

    /**
     * Disparado pelo layer PRESENTER quando o VIEW passa por uma
     * reconstrução/destruição. Útil como referência para parar tarefas
     * sendo realizadas em background Threads
     *
     * @param isChangingConfiguration   Informa se está ocorrendo uma
     *                                  mudança de configuração
     */
    @Override
    public void onDestroy(boolean isChangingConfiguration) {

    }
}

Para Presenter extenda GenericPresenter <RequiredPresenterOps, ProvidedModelOps, RequiredViewOps, ModelType extends ModelOps<RequiredPresenterOps> > implements PresenterOps<RequiredViewOps>

public class MainPresenter
        extends GenericPresenter
                        <MVP_MainActivity.RequiredPresenterOps,
                        MVP_MainActivity.ProvidedModelOps, MVP_MainActivity.RequiredViewOps,
                        MainModel>
        implements
            MVP_MainActivity.RequiredPresenterOps,
            MVP_MainActivity.ProvidedPresenterOps
{

    /**
     * Operação invocada durante a criação de View em
     * {@link GenericMVPActivity#onCreate(Class, Object)}
     * Responsável por inicializar Model e armazenar referência das
     * opeações em View.
     *
     * 1 - é obrigatório invocar {@link GenericPresenter#onCreate(Class, Object)}
     * antes de qualquer atividade
     * 2 - é obrigatório invocar {@link GenericPresenter#setView(Object)}
     * passando {@param view}
     *
     * @param view  A instância atual
     */
    @Override
    public void onCreate(MVP_MainActivity.RequiredViewOps view) {
        super.onCreate(MainModel.class, this);
        setView( view );
    }

    /**
     * Operação invocada após a reconstrução da View
     *
     * 1 - é obrigatório invocar {@link GenericPresenter#setView(Object)}
     * passando {@param view}
     * @param view  A instância View atual
     */
    @Override
    public void onConfigurationChange(MVP_MainActivity.RequiredViewOps view) {
        setView(view);
    }


    /**
     * Disparado pela {@link GenericMVPActivity} para informar um evento onBackPressed
     */
    @Override
    public void onBackPressed() {

    }
}

Para View extenda GenericMVPActivity <RequiredViewOps, ProvidedPresenterOps, PresenterType extends PresenterOps<RequiredViewOps>> extends ActivityKeyBoardDetector implements ActivityView  ou  GenericMVPFragment< RequiredActivityOps, RequiredViewOps, ProvidedPresenterOps, PresenterType extends PresenterOps<RequiredViewOps>> extends Fragment implements ContextView

public class MainActivity
        extends
            GenericMVPActivity<MVP_MainActivity.RequiredViewOps,
                                    MainPresenter,
                                    MainPresenter>
        implements
            MVP_MainActivity.RequiredViewOps{

    /**
     * Método padrão de criação de Atividades
     * 1 - {@link super#onCreate(Class, Object)} deve obrigatóriamente
     *     ser chamado na sequência ao método {@link super#onCreate(Bundle)}
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // super método obrigatório
        super.onCreate(MainPresenter.class,this);
        setContentView(R.layout.activity_main);
    }
}

Evitando problemas

  • Quando acessar getView()  de Presenter, sempre verifique se o resultado não será nulo, pois o layer view poderá não estar disponível, como no resultado de uma Thread que estava rodando no background e retornou o resultado após a destruição de View.
  • Utilize múltiplos Presenter para Views muito complexas.
  • Caso sua Activity possua muitos Fragmentos, cada um com seu Presenter, a solução mais prática será passar eventos entre os Fragmentos utilizando EventBus ou Broadcast. É claro que você pode fazer com interfaces, mas provavelmente ficará confuso demais.
  • Sempre chame super.onCreate(<Presenter.class>,<RequiredViewOps>);  quando subscrever o método onCreate(Bundle savedInstanceState)  no layer View.
  • Sempre chame super.onCreate(<Model.class>, <RequiredPresenterOps>);  e setView( view );  quando subscrever o método onCreate(MVP_MainActivity.RequiredViewOps view)  em Presenter.
  • Sempre redefina view  em Presenter durante as mudanças de configuração.
    @Override
    public void onConfigurationChange(MVP_MainActivity.RequiredViewOps view) {
       setView(view);
    }

     


Also published on Medium.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *