├── modelos └── Note.java ├── README.md ├── MainModel.java ├── MainMVP.java ├── MainActivity.java ├── MainPresenter.java └── StateMaintainer.java /modelos/Note.java: -------------------------------------------------------------------------------- 1 | package com.tinmegali.mvp_tutorial.modelos; 2 | 3 | /** 4 | * --------------------------------------------------- 5 | * Created by Tin Megali on 26/02/16. 6 | * Project: MVP_Tutorial 7 | * --------------------------------------------------- 8 | * tinmegali.com 9 | * Model View Presenter (MVP) no Android. 3 | 4 | Simplified implementation of Model View Presenter pattern in Android.
5 |
6 |
7 |

Tutorial-Android-Model-View-Presenter-MVP

8 | 9 | Implementação simplificada do padrão Model View Presenter (MVP) no ambiente Android.
10 | Parte integrante do tutorial Model View Presenter (MVP) no Android. 11 | 12 | Caso precise de um framework MVP mais robusto, utilize este. 13 | 14 |

Diagrama da implementação Model View Presenter

15 | 16 | 17 |

Ciclo de vida de View (Activity) e influência no Model View Presenter

18 | 19 | 20 | -------------------------------------------------------------------------------- /MainModel.java: -------------------------------------------------------------------------------- 1 | package com.tinmegali.mvp_tutorial; 2 | 3 | import android.util.Log; 4 | 5 | import com.tinmegali.mvp_tutorial.modelos.Note; 6 | 7 | /** 8 | * --------------------------------------------------- 9 | * Created by Tin Megali on 26/02/16. 10 | * Project: MVP_Tutorial 11 | * --------------------------------------------------- 12 | * tinmegali.com 13 | * tinmegali.com 11 | * tinmegali.com 18 | * (mView); 41 | this.mModel = new MainModel(this); 42 | } 43 | 44 | /** 45 | * Sent from Activity after a configuration changes 46 | * 47 | * Disparado por Activity após mudança de configuração 48 | * 49 | * @param view View reference 50 | */ 51 | @Override 52 | public void onConfigurationChanged(MainMVP.RequiredViewOps view) { 53 | Log.d(TAG, "onConfigurationChanged()"); 54 | 55 | mView = new WeakReference<>(view); 56 | } 57 | 58 | /** 59 | * Receives {@link MainActivity#onDestroy()} event 60 | * @param isChangingConfig Config change state 61 | * 62 | * Recebe evento {@link MainActivity#onDestroy()} 63 | * @param isChangingConfig Se está mudando de config 64 | */ 65 | @Override 66 | public void onDestroy(boolean isChangingConfig) { 67 | Log.d(TAG, "onDestroy(isChangingConfig:"+isChangingConfig+")"); 68 | mView = null; 69 | mIsChangingConfig = isChangingConfig; 70 | if ( !isChangingConfig ) { 71 | mModel.onDestroy(); 72 | } 73 | } 74 | 75 | 76 | /** 77 | * Called by user interaction from {@link MainActivity} 78 | * creates a new Note 79 | * 80 | * Chamado por {@link MainActivity} com a 81 | * interação do usuário de pedido para inserção de 82 | * nova nota 83 | */ 84 | @Override 85 | public void newNote(String noteText) { 86 | Log.d(TAG, "newNote()"); 87 | Note note = new Note(); 88 | note.setText(noteText); 89 | note.setDate(getDate()); 90 | mModel.insertNote(note); 91 | } 92 | 93 | /** 94 | * Called from {@link MainActivity}, 95 | * Removes a Note 96 | * 97 | * Chamado por {@link MainActivity}, pedido 98 | * para remoção de nota 99 | */ 100 | @Override 101 | public void deleteNote(Note note) { 102 | Log.d(TAG, "deleteNote()"); 103 | mModel.removeNote(note); 104 | } 105 | 106 | /** 107 | * Called from {@link MainModel} 108 | * when a Note is inserted successfully 109 | * 110 | * Recebe chamado de {@link MainModel} quando 111 | * Nota for inserida com sucesso no DB 112 | */ 113 | @Override 114 | public void onNoteInserted(Note novaNote) { 115 | Log.d(TAG, "onNoteInserted()"); 116 | mView.get().showToast("New " + novaNote.getDate()); 117 | } 118 | 119 | /** 120 | * Receives call from {@link MainModel} 121 | * when Note is removed 122 | * 123 | * Recebe chamado de {@link MainModel} quando 124 | * Nota for removida do DB 125 | */ 126 | @Override 127 | public void onNoteRemoved(Note removedNote) { 128 | Log.d(TAG, "onNoteRemoved()"); 129 | mView.get().showToast("Note " + removedNote.getDate() + " removed"); 130 | } 131 | 132 | /** 133 | * receive errors 134 | * 135 | * Recebe erros 136 | */ 137 | @Override 138 | public void onError(String errorMsg) { 139 | Log.d(TAG, "onError()"); 140 | mView.get().showAlert(errorMsg); 141 | } 142 | 143 | 144 | /** 145 | * Returns current date 146 | * 147 | * Retorna data atual 148 | */ 149 | private String getDate(){ 150 | Log.d(TAG, "getDate()"); 151 | return new SimpleDateFormat("EEEE, dd/MM, kk:mm", Locale.getDefault()).format(new Date()); 152 | } 153 | 154 | private Note getNote(String noteText){ 155 | Log.d(TAG, "getNote()"); 156 | Note note = new Note(); 157 | note.setText(noteText); 158 | note.setDate( getDate() ); 159 | return note; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /StateMaintainer.java: -------------------------------------------------------------------------------- 1 | package com.tinmegali.mvp_tutorial; 2 | 3 | import android.app.Fragment; 4 | import android.app.FragmentManager; 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | 8 | import java.lang.ref.WeakReference; 9 | import java.util.HashMap; 10 | 11 | /** 12 | * --------------------------------------------------- 13 | * Created by Tin Megali on 26/02/16. 14 | * Project: MVP_Tutorial 15 | * --------------------------------------------------- 16 | * tinmegali.com 17 | * (fragmentManager); 40 | mStateMaintenerTag = stateMaintainerTAG; 41 | } 42 | 43 | /** 44 | * Create the state maintainer fragment 45 | * @return true: the frag was created for the first time 46 | * false: recovering the object 47 | * 48 | * cria o fragmento responsável por armazenar o objetos 49 | * @return true: criou o framentos e rodou pela primeira vez 50 | * false: o objeto já foi criado, portanto é apenas recuperado 51 | */ 52 | public boolean firstTimeIn() { 53 | try { 54 | // Recovering the reference 55 | // Recuperando referência 56 | mStateMaintainerFrag = (StateMngFragment) 57 | mFragmentManager.get().findFragmentByTag(mStateMaintenerTag); 58 | 59 | // Creating a new RetainedFragment 60 | // Criando novo RetainedFragment 61 | if (mStateMaintainerFrag == null) { 62 | Log.d(TAG, "Creating a new RetainedFragment " + mStateMaintenerTag); 63 | mStateMaintainerFrag = new StateMngFragment(); 64 | mFragmentManager.get().beginTransaction() 65 | .add(mStateMaintainerFrag, mStateMaintenerTag).commit(); 66 | return true; 67 | } else { 68 | Log.d(TAG, "Returns a existent retained fragment existente " + mStateMaintenerTag); 69 | return false; 70 | } 71 | } catch (NullPointerException e) { 72 | Log.w(TAG, "Erro firstTimeIn()"); 73 | return false; 74 | } 75 | } 76 | 77 | 78 | /** 79 | * Insert Object to be preserved during configuration change 80 | * @param key Object's TAG reference 81 | * @param obj Object to maintain 82 | * 83 | * Insere objeto a serem presenrvados durante mudanças de configuração 84 | */ 85 | public void put(String key, Object obj) { 86 | mStateMaintainerFrag.put(key, obj); 87 | } 88 | 89 | /** 90 | * Insert Object to be preserved during configuration change 91 | * Uses the Object's class name as a TAG reference 92 | * Should only be used one time by type class 93 | * @param obj Object to maintain 94 | * 95 | * Insere objeto a serem presenrvados durante mudanças de configuração. 96 | * Utiliza a classe do Objeto como referência futura. 97 | * Só deve ser utilizado somente uma vez por classe, caso contrário haverá 98 | * possíveis conflitos na recuperação dos dados 99 | */ 100 | public void put(Object obj) { 101 | put(obj.getClass().getName(), obj); 102 | } 103 | 104 | 105 | /** 106 | * Recovers saved object 107 | * @param key TAG reference 108 | * @param Class type 109 | * @return Objects 110 | * 111 | * Recupera o objeto salvo 112 | */ 113 | @SuppressWarnings("unchecked") 114 | public T get(String key) { 115 | return mStateMaintainerFrag.get(key); 116 | 117 | } 118 | 119 | /** 120 | * Verify the object existence 121 | * @param key Obj TAG 122 | * 123 | * Verifica a existência de um objeto com a chave fornecida 124 | */ 125 | public boolean hasKey(String key) { 126 | return mStateMaintainerFrag.get(key) != null; 127 | } 128 | 129 | 130 | /** 131 | * Save and manages objects that show be preserved 132 | * during configuration changes. 133 | * 134 | * Armazena e administra os objetos que devem ser preservados 135 | * durante mudanças de configuração. 136 | */ 137 | public static class StateMngFragment extends Fragment { 138 | private HashMap mData = new HashMap<>(); 139 | 140 | @Override 141 | public void onCreate(Bundle savedInstanceState) { 142 | super.onCreate(savedInstanceState); 143 | // Grants that the frag will be preserved 144 | 145 | // Garante que o Fragmento será preservado 146 | // durante mudanças de configuração 147 | setRetainInstance(true); 148 | } 149 | 150 | /** 151 | * Insert objects 152 | * @param key reference TAG 153 | * @param obj Object to save 154 | * 155 | * Insere objetos no hashmap 156 | */ 157 | public void put(String key, Object obj) { 158 | mData.put(key, obj); 159 | } 160 | 161 | /** 162 | * Insert obj using class name as TAG 163 | * @param object obj to save 164 | * 165 | * Insere objeto utilizando o nome da classe como referência 166 | */ 167 | public void put(Object object) { 168 | put(object.getClass().getName(), object); 169 | } 170 | 171 | /** 172 | * Recover obj 173 | * @param key reference TAG 174 | * @param Class 175 | * @return Obj saved 176 | * 177 | * Recupera objeto salvo no hashmap 178 | */ 179 | @SuppressWarnings("unchecked") 180 | public T get(String key) { 181 | return (T) mData.get(key); 182 | } 183 | } 184 | 185 | } 186 | --------------------------------------------------------------------------------