Imprimir este capítuloImprimir este capítulo

Livro 3 - Projeto Agenda de Contatos - Parte 3

4. ViewModel e vinculação de dados

4.2. AddEditViewModel

Implementação da AddEditViewModel

A AddEditViewModel deve ser implementada para armazenar um contato específico e abstrair as solicitação ao repositório para adicionar um novo contato ou editar um já existente. Criamos o método getContactById para solicitar ao repositório um contato a partir de seu id e os métodos insert e update para o encaminhamento das operações ao repositório.

package ...

import android.app.Application;

import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;

import br.com.bcalegaro.agendacontatos.data.Contact;
import br.com.bcalegaro.agendacontatos.data.ContactsRepository;

public class AddEditViewModel extends AndroidViewModel {
private LiveData<Contact> contact;
private ContactsRepository mRepository;

public AddEditViewModel (Application application) {
super(application);
mRepository = new ContactsRepository(application);
}

public LiveData<Contact> getContactById(int id) {
contact = mRepository.getContactById(id);
return contact;
}

public void insert(Contact contact) { mRepository.insert(contact); }

public void update(Contact contact) { mRepository.update(contact); }
}

Vinculação dos dados na AddEditFragment

Para fazer a vinculação dos dados da ViewModel ao fragmento vamos modificar o método onActivityCreated de AddEditFragment. Nesse fragmento devemos, ou criar um novo contato e assim apresentar dados em branco nas caixas de texto, ou buscar as informações de um contato específico e apresentá-las na tela. Fazemos isso através da solicitação a ViewModel com o método getContactById e configurando que ao ser retornado os dados as informações na tela sejam atualizada.

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// cria uma ViewModel para o fragmento
addEditViewModel = new ViewModelProvider(this).get(AddEditViewModel.class);
// se estiver editando um contato existente atualiza a tela com os valores
if (addingNewContact == false) {
// usa a ViewModel para solicitar a busca pelo novo contato
addEditViewModel.getContactById(contactID).observe(getViewLifecycleOwner(), new Observer<Contact>() {
@Override
public void onChanged(@Nullable final Contact contact) {
// atualiza as informações da tela com os dados do contato lido
nameTextInputLayout.getEditText().setText(contact.getName());
phoneTextInputLayout.getEditText().setText(contact.getPhone());
emailTextInputLayout.getEditText().setText(contact.getEmail());
}
});
}
}

Ademais, precisamos modificar o método saveContact para encaminhar as solicitações corretas ao repositório. Ou seja, as solicitação de inserção de um novo contato ou edição de um contato já existente.

Primeiramente adicione os seguintes campos a classe:

// componentes EditText para informações de contato
private TextInputLayout nameTextInputLayout;
private TextInputLayout phoneTextInputLayout;
private TextInputLayout emailTextInputLayout;

Inicialize os campos corretamente na criação do fragmento :

@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
// cria o fragmento com o layout do arquivo add_edit_fragment.xml
View view = inflater.inflate(R.layout.add_edit_fragment, container, false);
// obtem as referências dos componentes
nameTextInputLayout = view.findViewById(R.id.nameTextInputLayout);
phoneTextInputLayout = view.findViewById(R.id.phoneTextInputLayout);
emailTextInputLayout = view.findViewById(R.id.emailTextInputLayout);
// configura o receptor de eventos do FAB
saveContactFAB = view.findViewById(R.id.saveButton);
saveContactFAB.setOnClickListener(saveContactButtonClicked);
// acessa a lista de argumentos enviada ao fragmento em busca do ID do contato
Bundle arguments = getArguments();
contactID = arguments.getInt(CONTACT_ID);
// verifica se o fragmento deve criar um novo contato ou editar um já existente
if (contactID == NEW_CONTACT) {
// usa a flag para sinalizar que é um novo contato
addingNewContact = true;
} else {
// usa a flag para sinalizar que é uma edição
addingNewContact = false;
}
return view;
}

Por fim, modifquei o método saveContact.

// salva informações de um contato no banco de dados
private void saveContact() {
// faz a leitura dos dados inseridos
String name = nameTextInputLayout.getEditText().getText().toString();
String phone = phoneTextInputLayout.getEditText().getText().toString();
String email = emailTextInputLayout.getEditText().getText().toString();
// caso for adição de uma novo contato
if (addingNewContact) {
// cria um contato sem um ID pois ele será adicionado automaticamente no banco de dados
Contact contact = new Contact(name, phone, email);
// solicita a ViewModel a inserção do novo contato
addEditViewModel.insert(contact);
} else {
// cria um contato com o mesmo ID e atualiza o seus valores
Contact contact = new Contact(contactID, name, phone, email);
// solicita a ViewModel a atualização do contato
addEditViewModel.update(contact);
}
//Solicita a naveção voltar uma tela
Navigation.findNavController(getView()).popBackStack();
}