Tutorial Android #12 – Editando Registros do Banco de Dados

Padrão

Olá pessoal!

No último post, tornamos o nosso aplicativo Lista de Restaurantes. No post de hoje, vamos aprimorar a forma como ele lida com o banco, fazendo com que os registros inseridos possam ser editados. Além disso, também faremos uma mudança no visual da aplicação, retirando as abas e colocar a tela de adição de restaurantes como uma opção no menu.

Prontos para começar? 😀

O primeiro passo é criarmos uma nova Activity, que será onde ficará, a partir de agora, o nosso formulário de cadastro (e consequentemente, de edição). Separaremos as funções da nossa Activity inicial. Então, crie a classe FormularioDetalhes.

package net.rafaeltoledo.restaurante;

import android.app.Activity;
import android.os.Bundle;

public class FormularioDetalhes extends Activity {

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	}
}

Por enquanto, esta Activity não tem nenhum layout atribuído, já que ainda não criamos o seu layout.

Antes de utilizar esta Activity em nosso projeto, precisamos declará-la no arquivo AndroidManifest.xml. Ele encontra-se na raiz da árvore do projeto.

Abra-o e selecione a aba inferior AndroidManifest.xml para abri-lo para a edição. Dentro do nó application, adicionaremos um novo nó activity.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.rafaeltoledo.restaurante"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".ListaRestaurantes" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".FormularioDetalhes">
        </activity>
    </application>

</manifest>

Prosseguindo, precisamos iniciar esta Activity quando clicarmos sobre um dos itens da lista. Assim, modifique o onListClick dessa forma:

private OnItemClickListener onListClick = new OnItemClickListener() {
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		Intent i = new Intent(ListaRestaurantes.this, FormularioDetalhes.class);
		startActivity(i);
	}
};

Se quiser testar a aplicação, ela deve exibir uma tela vazia ao clicar em algum item da lista.

Continuando, vamos agora fazer a migração do formulário para a nova Activity. Primeiramente, crie o arquivo form_detalhes.xml na pasta res/layout, podendo utilizar o main.xml como base para ele:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:stretchColumns="1" >
    <TableRow>
        <TextView android:text="Nome:"/>
        <EditText android:id="@+id/nome"/>
    </TableRow>
    <TableRow>
    	<TextView android:text="Endereço:"/>
    	<EditText android:id="@+id/end"/>
    </TableRow>
    <TableRow>
    	<TextView android:text="Tipo:"/>
    	<RadioGroup android:id="@+id/tipos">
    		<RadioButton android:id="@+id/rodizio"
       			android:text="Rodízio"/>
    		<RadioButton android:id="@+id/fast_food"
        		android:text="Fast Food"/>
        	<RadioButton android:id="@+id/a_domicilio"
            	android:text="A Domicílio"/>
   		</RadioGroup>
	</TableRow>
	<TableRow>
		<TextView android:text="Anotações:"/>
    	<EditText android:id="@+id/anotacoes"
    		android:singleLine="false"
    		android:gravity="top"
    		android:lines="2"
    		android:scrollHorizontally="false"
    		android:maxLines="2"
    		android:maxWidth="200sp"/>
    </TableRow>
    <Button android:id="@+id/salvar"
    	android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Salvar"/>
</TableLayout>

Agora, volte a Activity FormularioDetalhes e adicione esta linha ao final do método onCreate:

setContentView(R.layout.form_detalhes);

O próximo passo é mover toda a lógica do formulário para a nossa classe FormularioDetalhes. Primeiramente, adicione os atributos da classe que estavam na ListaRestaurantes para a FormularioDetalhes:

EditText nome = null;
EditText endereco = null;
EditText anotacoes = null;
RadioGroup tipos = null;
GerenciadorRestaurantes gerenciador;

Agora, copie a busca aos widgets no formulário do método onCreate() do ListaRestaurantes para o FormularioDetalhes, no mesmo local.

gerenciador = new GerenciadorRestaurantes(this);

nome = (EditText) findViewById(R.id.nome);
endereco = (EditText) findViewById(R.id.end);
anotacoes = (EditText) findViewById(R.id.anotacoes);
tipos = (RadioGroup) findViewById(R.id.tipos);

Button salvar = (Button) findViewById(R.id.salvar);
salvar.setOnClickListener(onSave);

Por fim, vamos copiar a implementação do nosso listener onSave para a classe FormularioDetalhes, porém retirando a parte que trata da inserção no banco de dados:

private OnClickListener onSave = new OnClickListener() {

	public void onClick(View arg0) {
		String tipo = null;

		switch (tipos.getCheckedRadioButtonId()) {
		case R.id.rodizio:
			tipo = "rodizio";
			break;
		case R.id.fast_food:
			tipo = "fast_food";
			break;
		case R.id.a_domicilio:
			tipo = "a_domicilio";
			break;
		}
	}
};

Agora é hora de “limparmos” a interface original do aplicativo, no main.xml. Retiraremos o formulário que existia e as abas, além do ajuste no layout para abrigar somente a lista. O que nos resta é isso:

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/list"
	android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

Após isso, exclua a pasta layout_land e o arquivo main.xml dentro dela (calma, calma… voltaremos a mexer com ele em posts futuros :)).

No momento, ListaRestaurantes estende TabActivity. Porém, como modificamos a estrutura de nossa aplicação, isso não é mais necessário. Modifique a classe, de forma que ListaRestaurante estenda ListActivity. Em seguida, modifique o método onCreate() para retirar os códigos que diziam respeito às abas que utilizávamos:

@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);

	gerenciador = new GerenciadorRestaurantes(this);
	listaRestaurantes = gerenciador.obterTodos();
	startManagingCursor(listaRestaurantes);
	adaptador = new AdaptadorRestaurante(listaRestaurantes);
	setListAdapter(adaptador);
}

Antes de seguirmos em frente, vamos analisar o que vamos fazer: o FormularioDetalhes será utilizado tanto na criação de novos restaurantes quando na edição de restaurantes já cadastrados. Além disso, ele precisa saber, quando estiver editando, qual restaurante se trata. Para isso, precisamos do identificador do restaurante (o campo _id do banco de dados).

Primeiramente, vamos criar um atributo para a classe ListaRestaurantes:

public final static String _ID = "net.rafaeltoledo.restaurante._ID";

Após isso, vamos mudar o objeto onListClick para um onListItemClick(), onde vamos passar o valor do id para a outra Activity:

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
	Intent i = new Intent(ListaRestaurantes.this, FormularioDetalhes.class);
	i.putExtra(_ID, String.valueOf(id));
	startActivity(i);
}

Em seguida, adicione o seguinte atributo na classe FormularioDetalhes:

String idRestaurante = null;

Este atributo será nulo se estivermos adicionando um novo restaurante, ou o identificador, caso estejamos editando um restaurante.

Como criamos o GerenciadorRestaurantes no método onCreate(), precisamos encerrá-lo no método onDestroy():

@Override
public void onDestroy() {
	super.onDestroy();
	gerenciador.close();
}

Como agora temos o ID como controle dos restaurantes, precisamos de um método que nos retorne o Restaurante com o identificador correspondente. Adicione o seguinte método a classe GerenciadorRestaurantes:

public Cursor obterPorId(String id) {
	String[] argumentos = {id};

	return getReadableDatabase().rawQuery(
			"SELECT _id, nome, endereco, tipo, anotacoes " +
			"FROM restaurantes WHERE _id = ?", argumentos);
}

Agora, adicione o seguinte trecho ao fim do método onCreate() da classe FormularioDetalhes:

idRestaurante = getIntent().getStringExtra(ListaRestaurantes._ID);

if (idRestaurante != null) {
	carregar();
}

Adicione, então, a implementação do método carregar():

private void carregar() {
	Cursor c = gerenciador.obterPorId(idRestaurante);

	c.moveToFirst();
	nome.setText(gerenciador.obterNome(c));
	endereco.setText(gerenciador.obterEndereco(c));
	anotacoes.setText(gerenciador.obterAnotacoes(c));

	if (gerenciador.obterTipo(c).equals("rodizio")) {
		tipos.check(R.id.rodizio);
	} else if (gerenciador.obterTipo(c).equals("fast_food")) {
		tipos.check(R.id.fast_food);
	} else {
		tipos.check(R.id.a_domicilio);
	}

	c.close();
}

Agora, vamos adicionar a opção de menu Adicionar para que possamos, a partir da listagem (que agora será a tela principal do aplicativo), inserir um novo restaurante. Modifique o arquivo opcao.xml que encontra-se em res/menu.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
	<item android:id="@+id/adicionar"
	    android:title="Adicionar"
	    android:icon="@drawable/adicionar"/>
</menu>

Este item de mídia é padrão do Android, e pode ser encontrado no seu diretório de instalação do SDK, em platforms -> versão do Android que está usando (no meu caso, android-8 (ou 2.2)) -> data -> res -> tamanho de tela (podemos utilizar drawable-mdpi). Procure pelo ícone ic_menu_add.png. Copie-o e coloque na pasta res/drawable da sua aplicação. Para padronizar o nome, eu o renomeei para adicionar.png. 🙂

Agora que já temos o menu, vamos ajustar a classe ListaRestaurantes para manipulá-lo corretamente. Vamos novamente implementar o método onCreateOptionsMenu():

@Override
public boolean onCreateOptionsMenu(Menu menu) {
	new MenuInflater(this).inflate(R.menu.opcao, menu);

	return super.onCreateOptionsMenu(menu);
}

E adicione, também, a implementação de onOptionsItemSelected():

@Override
public boolean onOptionsItemSelected(MenuItem item) {
	if (item.getItemId() == R.id.adicionar) {
		startActivity(new Intent(ListaRestaurantes.this, FormularioDetalhes.class));
		return true;
	}

	return super.onOptionsItemSelected(item);
}

Bom, lá na nossa classe GerenciadorRestaurantes, temos o método para inserir um novo restaurante, mas não temos o método para atualizar. Portanto, adicione o seguinte método à classe:

public void atualizar(String id, String nome, String endereco, String tipo, String anotacoes) {
	ContentValues valores = new ContentValues();
	String[] argumentos = {id};

	valores.put("nome", nome);
	valores.put("endereco", endereco);
	valores.put("tipo", tipo);
	valores.put("anotacoes", anotacoes);

	getWritableDatabase().update("restaurantes", valores, "_id=?", argumentos);
}

Por fim, precisamos adicionar o comportamento do botão Salvar no formulário. Modifique a implementação do onSave na classe FormularioDetalhes para verificar se a operação é de inclusão ou alteração:

private OnClickListener onSave = new OnClickListener() {
	public void onClick(View arg0) {
		String tipo = null;

		switch (tipos.getCheckedRadioButtonId()) {
		case R.id.rodizio:
			tipo = "rodizio";
			break;
		case R.id.fast_food:
			tipo = "fast_food";
			break;
		case R.id.a_domicilio:
			tipo = "a_domicilio";
			break;
		}

		if (idRestaurante == null) {
			gerenciador.inserir(nome.getText().toString(),
					endereco.getText().toString(),
					tipo, anotacoes.getText().toString());
		} else {
			gerenciador.atualizar(idRestaurante,
					nome.getText().toString(),
					endereco.getText().toString(),
					tipo, anotacoes.getText().toString());
		}

		finish();
	}
};

Verifique se não há código duplicado, corrija os imports (Ctrl + Shift + O) e pronto! Já temos nossa aplicação funcionando!

Como o post já está bem grande, não vou colocar a listagem das classes. Caso esteja com problemas, você pode baixar o projeto completo aqui.

Bons estudos e até a próxima galera!

9 comentários sobre “Tutorial Android #12 – Editando Registros do Banco de Dados

  1. Carlos Magno M Santos

    Rafael, onde está o procedimento de atualização, não encontrei ele, pode ajudar? Grato Carlos Magno

Deixe uma resposta