Está en la página 1de 22

24/2/2020 Tutorial # 14 - Guardar notas

Página 1

Tutorial # 14 - Guardar notas

Sería bueno si el usuario pudiera agregar algunas notas personales al capítulo de que ella es
lectura, si eso sirve como comentario, puntos a investigar, quejas
sobre el cabello del autor (o la falta del mismo), o lo que sea.

Entonces, en este capítulo, agregaremos un nuevo fragmento y una nueva actividad para permitir al usuario
agregue notas por capítulo, a través de un gran widget EditText . Esas notas se almacenarán en un
Base de datos SQLite.

Esta es una continuación del trabajo que hicimos en el tutorial anterior .

Puede encontrar los resultados del tutorial anterior y los resultados de este tutorial en el
repositorio GitHub del libro.

Paso # 1: Agregar una base de datos Helper


El primer paso para trabajar con SQLite es agregar una implementación de
SQLiteOpenHelper , que haremos aquí, llamado DatabaseHelper .

Haga clic derecho sobre el paquete com.commonsware.empublite en su directorio java /


y elija Nuevo> Clase Java en el menú contextual. Complete DatabaseHelper como el
name y android.database.sqlite.SQLiteOpenHelper como la superclase. Luego,
haga clic en Aceptar para crear la clase vacía.

Luego, reemplace el contenido de esa clase con lo siguiente:

paquete com . Commonsware . empublita ;

importar android.content.Context ;

https://translate.googleusercontent.com/translate_f 1/22
24/2/2020 Tutorial # 14 - Guardar notas
importar android.database.sqlite.SQLiteDatabase ;

707

Página 2

T utorial # 14 - S AVING N OTES

importar android.database.sqlite.SQLiteOpenHelper ;

base de datos de clase pública


DatabaseHelper extiende SQLiteOpenHelper {
Private static final String DATABASE_NAME = "empublite.db" ;
privado estático final int SCHEMA_VERSION = 1;
DatabaseHelper estática privada singleton = null ;

Base de datos estática sincronizada getInstance ( Contexto ctxt ) {


sincronizado
if ( singleton == nulo ) {
singleton = new DatabaseHelper ( ctxt . getApplicationContext ());
}

retorno ( singleton );
}

DatabaseHelper privado ( contexto ctxt ) {


super ( ctxt , DATABASE_NAME , null , SCHEMA_VERSION );
}

@Anular
public void onCreate ( SQLiteDatabase db ) {
db . execSQL ( "CREAR TABLA notas (posición INTEGER PRIMARY KEY, prose TEXT);" );
}

@Anular
public void onUpgrade ( SQLiteDatabase db , int oldVersion ,
int newVersion ) {
lanzar nueva RuntimeException ( "Esto no debería llamarse" );
}
}

Paso # 2: Examinando DatabaseHelper


Nuestra versión inicial de DatabaseHelper tiene algunas cosas:

• Tiene el constructor, proporcionando a la superclase el nombre de la base de datos.


archivo ( DATABASE_NAME ) y el número de revisión de nuestro esquema
( SCHEMA_VERSION ). Tenga en cuenta que el constructor es privado, ya que estamos utilizando el
patrón único, por lo que solo DatabaseHelper debería poder crear
Instancias de DatabaseHelper .
• Tiene el método onCreate () , invocado la primera vez que ejecutamos la aplicación en un
dispositivo o emulador, para permitirnos poblar la base de datos. Aquí, usamos execSQL ()
para definir una tabla de notas con una columna de posición (que indica nuestro capítulo) y
una columna en prosa (lo que el usuario escribe como nota).

https://translate.googleusercontent.com/translate_f 2/22
24/2/2020 Tutorial # 14 - Guardar notas

708

Página 3

T utorial # 14 - S AVING N OTES

• Tiene el método onUpgrade () , necesario porque SQLiteOpenHelper es


resumen, por lo que nuestra aplicación no se compilará sin una implementación. Hasta que nosotros
Sin embargo, si revisamos nuestro esquema, este método nunca debería llamarse, por lo que planteamos un
RuntimeException en la remota posibilidad de que se llama de forma inesperada.
• Tiene una instancia única de DatabaseHelper estática y un getInstance ()
método para inicializarlo perezosamente.

Como se señaló en el capítulo sobre bases de datos , es importante asegurarse de que todos los hilos estén
accediendo al mismo objeto SQLiteDatabase , para seguridad de subprocesos. Eso generalmente significa que tú
mantener un solo objeto SQLiteOpenHelper . Y, en nuestro caso, podríamos querer obtener
en esta base de datos de más de una actividad. Por lo tanto, vamos con el singleton
enfoque, para que todos trabajen con la misma instancia de DatabaseHelper .

Paso 3: crear un fragmento de nota


Tener una base de datos es bueno y todo, pero necesitamos trabajar en la interfaz de usuario para permitir a los usuarios
ingrese notas. Para hacer eso, comenzaremos con un NoteFragment .

Haga clic derecho sobre el paquete com.commonsware.empublite en su directorio java /


y elija Nuevo> Clase Java en el menú contextual. Rellene NoteFragment como el
name y android.app.Fragment como la superclase. Luego, haga clic en Aceptar para crear el
clase vacía

Luego, reemplace el contenido de esa clase con lo siguiente:

paquete com . Commonsware . empublita ;

importar android.app.Fragment ;
importar android.os.Bundle ;
importar android.view.LayoutInflater ;
importar android.view.View ;
importar android.view.ViewGroup ;
importar android.widget.EditText ;

NoteFragment de clase pública


NoteFragment extiende Fragment {
Private static final String KEY_POSITION = "posición" ;
editor privado de EditText = nulo ;

estática NoteFragment newInstance ( int posición ) {


NoteFragment frag = new NoteFragment ();
Bundle args = new Bundle ();

args . putInt ( KEY_POSITION , posición );

https://translate.googleusercontent.com/translate_f 3/22
24/2/2020 Tutorial # 14 - Guardar notas

709

Página 4

T utorial # 14 - S AVING N OTES

frag . setArguments ( args );

volver ( frag );
}

@Anular
pública Vista onCreateView ( LayoutInflater de inflado ,
ViewGroup container ,
Paquete salvadoInstanceState ) {
Ver resultado = inflador . inflar ( R . diseño . editor , contenedor , falsa );

editor = ( EditText ) resultado . findViewById ( R . ID . editor );

retorno ( resultado );
}

private int getPosition () {


return ( getArguments (). getInt ( KEY_POSITION , -1));
}
}

Tenga en cuenta que este fragmento utiliza el recurso res / layout / editor.xml que creamos
de vuelta en el Tutorial # 5 .

Paso # 4: Examinar NoteFragment


Nuestro NoteFragment es bastante sencillo y recuerda el
SimpleContentFragment que creamos en el Tutorial # 11 .

NoteFragment tieneun método de fábrica estático newInstance () . Este método crea un


instancia de NoteFragment , toma un int pasado (identificando el capítulo para el cual
estamos creando una nota), la coloca en un Paquete identificado como KEY_POSITION , entrega el
Agrupa el fragmento como sus argumentos y devuelve el recién creado
Nota Fragmento .

En onCreateView () , inflamos el recurso R.layout.editor que definimos y obtenemos


nuestras manos en nuestro widget EditText para su uso posterior.

Paso # 5: Creando la NoteActivity


Tener un fragmento sin mostrarlo no tiene sentido, por lo que necesitamos algo para
cargar un NoteFragment . Particularmente para teléfonos, la respuesta más simple es crear un

https://translate.googleusercontent.com/translate_f 4/22
24/2/2020 Tutorial # 14 - Guardar notas

710

Página 5

T utorial # 14 - S AVING N OTES

NoteActivity paraeso, paralelamente a la relación entre SimpleContentFragment


y SimpleContentActivity .

Haga clic derecho sobre el paquete com.commonsware.empublite en su directorio java /


y elija Nuevo> Actividad> Actividad vacía en el menú contextual. Llenar
NotaActividad como nombre, desmarque todas las casillas de verificación y haga clic en Aceptar para crear el
clase vacía

En la clase NoteActivity que se crea, reemplace la implementación actual con


el seguimiento:

paquete com . Commonsware . empublita ;

importar android.app.Activity ;
importar android.app.Fragment ;
importar android.os.Bundle ;

clase pública NoteActivity


NoteActivity extiende la actividad {
public static final String EXTRA_POSITION = "posición" ;

@Anular
public void onCreate ( Bundle savedInstanceState ) {
súper . onCreate ( savedInstanceState );

si ( getFragmentManager (). findFragmentById ( androide . R . de id . de contenido ) == nula ) {


int position = getIntent (). getIntExtra ( EXTRA_POSITION , -1);

if ( posición > = 0) {
Fragmento f = Nota Fragmento . newInstance ( posición );

getFragmentManager (). beginTransaction ()


. añadir ( androide . R . de id . de contenido , f ). commit ();
}
}
}
}

Paso # 6: Examinando NoteActivity


Como puede ver, esta es una actividad bastante trivial. En onCreate () , si estamos siendo creados
de nuevo, ejecutamos una FragmentTransaction para agregar un NoteFragment a nuestra actividad,
vertiéndolo en la pantalla completa ( android.R.id.content ). Aquí,
android.R.id.content identifica el contenedor en el que los resultados de

https://translate.googleusercontent.com/translate_f 5/22
24/2/2020 Tutorial # 14 - Guardar notas

711

Página 6

T utorial # 14 - S AVING N OTES

setContentView () iría:
es un contenedor suministrado por Activity en sí y sirve
como el contenedor más alto para nuestro contenido.

Sin embargo, esperamos que se nos pase un Intento adicional con el puesto
( EXTRA_POSITION ), que pasamos al método de fábrica NoteFragment .

Paso # 7: Agregar notas a la barra de acción


Por supuesto, nada de esto es útil si no le damos al usuario una forma de llegar al
Nota Actividad . Específicamente, podemos agregar una entrada de notas a nuestro res / menu / options.xml
recurso, para que aparezca un nuevo botón de barra de herramientas en la barra de acción de nuestra actividad principal.

Haga clic con el botón derecho sobre el directorio res / y elija Nuevo> Activo vectorial en el contexto
menú. Haga clic en el botón Icono y busque el icono "Crear":

Figura 290: Selector de iconos de Asset Studio, con Crear icono seleccionado

Haga clic en Aceptar para cerrar el selector de iconos. Luego haga clic en Siguiente y Finalizar para guardar este dibujo
recurso.

Desafortunadamente, este icono se mostrará en negro, cuando lo necesitemos en blanco


dado nuestro tema. Haga clic derecho sobre res / drawable / ic_create_black_24dp.xml , elija
Refactorizar> Cambiar nombre del menú contextual y cambiar el nombre a

https://translate.googleusercontent.com/translate_f 6/22
24/2/2020 Tutorial # 14 - Guardar notas

712

Página 7

T utorial # 14 - S AVING N OTES

ic_create_white_24dp.xml .Luego, abra res / drawable / ic_create_white_24dp.xml


y cambie el android: fillColor en el elemento <path> para que sea #FFFFFFFF en su lugar
de # FF000000 :

<vector xmlns: android = "http://schemas.android.com/apk/res/android"


android: ancho = "24dp"
android: height = "24dp"
android: viewportWidth = "24.0"
android: viewportHeight = "24.0" >
<camino
android: fillColor = "#FFFFFFFF"
android: pathData = "M3,17.25V21h3.75L17.81,9.94l-3.75, -3.75L3,17.25zM20.71,7.04c0.39, -0.39
0.39, -1.02 0, -1.41l-2.34, -2.34c-0.39, -0.39 -1.02, -0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83, -1.83z " />
</vector>

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / res / drawable / ic_create_white_24dp.xml )

A continuación, agregue un nuevo recurso de cadena, denominado notes , con un valor como Notes .

Luego, modifique res / menu / options.xml para que se vea así:

<? xml version = "1.0" encoding = "utf-8"?>


<menu xmlns: android = "http://schemas.android.com/apk/res/android" >

<artículo
android: id = "@ + id / notes"
android: icon = "@ drawable / ic_create_white_24dp"
android: showAsAction = "ifRoom | withText"
android: title = "@ string / notes" >
</item>
<artículo
android: id = "@ + id / settings"
android: icon = "@ drawable / ic_settings_black_24dp"
android: showAsAction = "nunca"
android: title = "@ string / settings" >
</item>
<artículo
android: id = "@ + id / help"
android: icon = "@ drawable / ic_help_outline_black_24dp"
android: title = "@ string / help" >
</item>
<artículo
android: id = "@ + id / about"
android: icon = "@ drawable / ic_info_outline_black_24dp"
android: title = "@ string / about" >
</item>

</menu>

https://translate.googleusercontent.com/translate_f 7/22
24/2/2020 Tutorial # 14 - Guardar notas

713

Página 8

T utorial # 14 - S AVING N OTES

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / res / menu / options.xml )

Finalmente, en EmPubLiteActivity , agregue el siguiente caso a la instrucción switch en


onOptionsItemSelected () :

caso R . id . notas :
startActivity ( nueva intención ( esto , NoteActivity . class )
. putExtra ( NoteActivity . EXTRA_POSITION ,
buscapersonas . getCurrentItem ()));

retorno ( verdadero );

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / EmPubLiteActivity.java )

Aquí, obtenemos la posición actualmente vista desde ViewPager y la pasamos como


EXTRA_POSITION extra a NoteActivity .

Paso # 8: Definir un evento NoteLoadedEvent


Querremos cargar notas de la base de datos en un hilo de fondo. Por lo tanto, nosotros
puede aplicar el mismo enfoque básico que usamos con ModelFragment , publicando un evento
en el greenrobot EventBus cuando se completa la carga, para entregar los resultados al
Nota Fragmento . Este paso creará un NoteLoadedEvent para manejar este caso.

Haga clic derecho sobre el paquete com.commonsware.empublite en su directorio java /


y elija Nuevo> Clase Java en el menú contextual. Complete NoteLoadedEvent como el
nombre y haga clic en Aceptar para crear la clase vacía.

Luego, reemplace el contenido de esa clase con lo siguiente:

paquete com . Commonsware . empublita ;

clase NoteLoadedEvent
NoteLoadedEvent {
posición int ;
Prosa de cuerdas ;

NoteLoadedEvent ( int position , String prose ) {


esta . posición = posición ;
esta . prosa = prosa ;
}

int getPosition () {
retorno ( posición );
}

https://translate.googleusercontent.com/translate_f 8/22
24/2/2020 Tutorial # 14 - Guardar notas
714

Página 9

T utorial # 14 - S AVING N OTES

String getProse () {
retorno ( prosa );
}
}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / NoteLoadedEvent.java )

Si lo prefiere, puede ver el contenido de este archivo en su navegador web a través de este GitHub
enlace.

Paso 9: cargar una nota de la base de datos


Luego, necesitamos agregar código en algún lugar que realmente consultará la base de datos (en un
subproceso de fondo) para cargar la nota para una determinada posición de ViewPager . Uno común
patrón es poner este tipo de lógica de acceso a la base de datos en su SQLiteOpenHelper
subclase, por lo que todo el código específico de su base de datos reside en un solo lugar. Eso es el
enfoque que tomaremos aquí, agregando un método loadNote () que bifurcará un hilo,
consultar la base de datos y publicar un NoteLoadedEvent como resultado.

Edite su DatabaseHelper para agregar su propia clase interna LoadThread , que recuerda a la
uno de ModelFragment :

clase privada LoadThread LoadThread extiende Thread {


posición int privada = -1;

LoadThread ( posición int ) {


super ();
esta . posición = posición ;
}

@Anular
public void run () {
Proceso . setThreadPriority ( Proceso . THREAD_PRIORITY_BACKGROUND );

Cadena [] args = { Cadena . valueOf ( posición )};


Cursor c =
getReadableDatabase (). rawQuery ( "SELECCIONAR prosa DE las notas WHERE position =?" , args );

if ( c . getCount ()> 0) {
c . moveToFirst ();

EventBus . getDefault (). post ( nuevo NoteLoadedEvent ( posición ,


c . getString (0)));
}

c . cerrar ();
}
}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / DatabaseHelper.java )

https://translate.googleusercontent.com/translate_f 9/22
24/2/2020 Tutorial # 14 - Guardar notas
715

Página 10

T utorial # 14 - S AVING N OTES

Aquí, usamos rawQuery () para recuperar la nota basada en una posición provista. Si
no hay tal nota, nuestro Cursor no tendrá filas, y hemos terminado. Si, sin embargo, nosotros
obtuvimos resultados en la consulta, luego publicamos un NoteLoadedEvent con el
posición y la prosa (el texto de la base de datos).

Deberá agregar una importación manualmente a android.os.Process , para poder


resuelva el método setThreadPriority () y su parámetro.

Además, agregue un método loadNote () a DatabaseHelper que bifurca este LoadThread :

nulo loadNote ( posición int ) {


nuevo LoadThread ( posición ). inicio ();
}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / DatabaseHelper.java )

Paso # 10: cargando la nota en el fragmento


Ahora que podemos consultar la base de datos y recuperar una nota (si hay alguna), podemos vincular eso a
la NoteFragment para cargar la nota para el fragmento de posición cuando el fragmento es
abrió. No solo necesitaremos llamar a loadNote () en DatabaseHelper , sino también
ser capaz de responder al NoteLoadedEvent cuando llegue.

Agregue el siguiente método onStart () a NoteFragment :

@Anular
public void onStart () {
súper . onStart ();

EventBus . getDefault (). registrarse ( esto );

if ( TextUtils . isEmpty ( editor . getText ())) {


DatabaseHelper db = DatabaseHelper . getInstance ( getActivity ());
db . loadNote ( getPosition ());
}
}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / NoteFragment.java )

Aquí, nos registramos para el EventBus . Entonces, si no tenemos ningún texto en EditText
widget, llamamos loadNote () en nuestra instancia singleton de DatabaseHelper , pasando
en la posición que gestiona nuestro fragmento. La razón para verificar si el
EditText está vacío es para manejar los cambios de configuración. Este fragmento no es un
fragmento retenido, por lo que será destruido y recreado. El valor por defecto

https://translate.googleusercontent.com/translate_f 10/22
24/2/2020 Tutorial # 14 - Guardar notas
716

Página 11

T utorial # 14 - S AVING N OTES

Sin embargo, la lógica onSaveInstanceState () de EditText retendrá


nuestra nota, por lo que no
desea volver a cargarlo desde la base de datos. Este enfoque no es óptimo, ya que lo haremos
terminar llamando a loadNote () en los casos en que podríamos saber que no hay nota.
Esa optimización es lo suficientemente compleja como para que no valga la pena para un conjunto de libros.
tutoriales, aunque es algo que quizás desee explorar en un grado comercial
solicitud.

A continuación, agregue el onStop () correspondiente a NoteFragment , para anular el registro de


EventBus :

@Anular
public void onStop () {
EventBus . getDefault (). anular el registro ( esto );

súper . onStop ();


}

Finalmente, agregue un método onNoteLoaded (NoteLoadedEvent) a NoteFragment , para que podamos


recibir el NoteLoadedEvent en el hilo principal de la aplicación:

@SuppressWarnings ( "sin usar" )


@Subscribe ( threadMode = ThreadMode . MAIN )
public void onNoteLoaded ( evento NoteLoadedEvent ) {
if ( event . getPosition () == getPosition ()) {
editor . setText ( evento . getProse ());
}
}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / NoteFragment.java )

Aquí, confirmamos que el evento es para la posición de nuestro fragmento, ya que es concebible
que este evento es para alguna otra nota, aunque eso es bastante improbable dada la forma en que
El usuario vería las notas. Dicho esto, si la nota es para nuestra posición, poblamos
la EditarTexto con la prosa nota.

Paso # 11: Actualización de la base de datos


Por supuesto, cargar notas de una base de datos está bien y bien ... excepto que no
tener notas en la base de datos. Realmente deberíamos arreglar eso.

Agregue una clase interna UpdateThread a DatabaseHelper :

clase privada UpdateThreadUpdateThread extiende Thread {


posición int privada = -1;

717
https://translate.googleusercontent.com/translate_f 11/22
24/2/2020 Tutorial # 14 - Guardar notas

Pagina 12

T utorial # 14 - S AVING N OTES

prosa de cadena privada = nulo ;

UpdateThread ( posición int , prosa de cuerda ) {


super ();
esta . posición = posición ;
esta . prosa = prosa ;
}

@Anular
public void run () {
Proceso . setThreadPriority ( Proceso . THREAD_PRIORITY_BACKGROUND );

Cadena [] args = { Cadena . valueOf ( posición ), prosa };


getWritableDatabase (). execSQL ( "INSERTAR O REEMPLAZAR EN notas (posición, prosa) VALORES (?,?)" ,
args );
}
}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / DatabaseHelper.java )

Aquí, usamos execSQL () para ejecutar una instrucción SQL INSERT O REPLACE . Como el
el nombre sugiere, esto insertará una nueva fila si no hay coincidencia en nuestra clave primaria
( posición ) De lo contrario, actualizará las otras columnas si hay una coincidencia.

Tenga en cuenta que no publicamos un evento aquí. Podríamos, si hubiera algo en la aplicación
eso necesitaba saber cuándo se actualizó una nota.

Además, agregue un método updateNote () a DatabaseHelper que bifurca este UpdateThread :

void updateNote ( int position , String prose ) {


nuevo UpdateThread ( posición , prosa ). inicio ();
}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / DatabaseHelper.java )

Paso # 12: guardar la nota


En algún lugar, necesitamos llamar a updateNote () . Un enfoque clásico de "escritorio" sería
tener un elemento de barra de acción "guardar" en NoteFragment , que el usuario necesitaría
Haga clic para guardar la nota. Sin embargo, esto no se ocupa de las interrupciones
La naturaleza de los teléfonos está muy bien. Por ejemplo, el usuario puede comenzar a escribir una nota,
luego terminas tomando una llamada telefónica. Si nuestro proceso se termina, dependiendo de cómo
el usuario intenta volver a nuestra aplicación, es posible que no tengamos la nota de nuestro guardado
estado de instancia

Un mejor enfoque, en muchos casos, es guardar datos en onStop () , cuando la actividad


se mueve hacia el fondo. Si existe la posibilidad de que el usuario no quiera

718
https://translate.googleusercontent.com/translate_f 12/22
24/2/2020 Tutorial # 14 - Guardar notas

Página 13

T utorial # 14 - S AVING N OTES

información parcialmente ingresada, puede guardarla en un área "lateral", como una temporal
archivo, y tratarlo cuando el usuario regrese a su aplicación. O simplemente podrías actualizar
el verdadero almacén de datos ... que es lo que haremos aquí.

Edite el método onStop () en NoteFragment para que tenga el siguiente aspecto:

@Anular
public void onStop () {
DatabaseHelper . getInstance ( getActivity ())
. updateNote ( getPosition (),
editor . getText (). toString ());

EventBus . getDefault (). anular el registro ( esto );

súper . onStop ();


}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / NoteFragment.java )

Aquí, actualizamos la nota. Esto es un poco ineficiente, ya que actualizamos la base de datos incluso si
el usuario no cambió el texto de la nota, ni siquiera si la nota está vacía. Ese
representa otra optimización que una aplicación de grado de producción podría desear seguir
pero se omite aquí en aras de la simplicidad.

Si compila y ejecuta la aplicación en un dispositivo o emulador, verá las nuevas "notas"


botón de la barra de herramientas en la barra de acción:

719

https://translate.googleusercontent.com/translate_f 13/22
24/2/2020 Tutorial # 14 - Guardar notas

Página 14

T utorial # 14 - S AVING N OTES

Figura 291: El nuevo elemento de la barra de acción

Al tocar eso, aparecerán las notas para cualquier posición de ViewPager en la que se encuentre
en. Ingresando algunas notas y presionando ATRÁS para salir de la actividad guardará esas
notas, que volverá a ver si vuelve a tocar el botón de la barra de herramientas de la barra de acciones. Si tu
cambiar las notas, presionando ATRÁS guardará las notas cambiadas en la base de datos, para ser
visto de nuevo más tarde cuando vuelva a las notas para esa posición ViewPager .

Paso # 13: Agregar un elemento de barra de acción Eliminar


El único problema con esta solución es que las notas nunca se van. Mientras el usuario
podría eliminar manualmente todo en EditText , sería bueno hacer que
quizás un poco más simple. En este paso, agregaremos un elemento de barra de acción que borrará el
EditText para el usuario.

Haga clic con el botón derecho sobre el directorio res / y elija Nuevo> Activo vectorial en el contexto
menú. Haga clic en el botón Icono y busque el icono "eliminar":

720

https://translate.googleusercontent.com/translate_f 14/22
24/2/2020 Tutorial # 14 - Guardar notas

Página 15

T utorial # 14 - S AVING N OTES

Figura 292: Selector de iconos de Asset Studio, con el icono Eliminar seleccionado

Haga clic en Aceptar para cerrar el selector de iconos. Cambie el nombre del recurso a
ic_delete_white_24dp . Luego haga clic en Siguiente y Finalizar para guardar este recurso dibujable.
Luego, abra res / drawable / ic_delete_white_24dp.xml y cambie el
android: fillColor en el elemento <path> para ser #FFFFFFFF en lugar de # FF000000 :

<vector xmlns: android = "http://schemas.android.com/apk/res/android"


android: ancho = "24dp"
android: height = "24dp"
android: viewportWidth = "24.0"
android: viewportHeight = "24.0" >
<camino
android: fillColor = "#FFFFFFFF"
android: pathData = "M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2, -0.9
2, -2V7H6v12zM19,4h-3.5l-1, -1h-5l-1,1H5v2h14V4z " />
</vector>

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / res / drawable / ic_delete_white_24dp.xml )

A continuación, agregue un nuevo recurso de cadena, denominado eliminar , con un valor como Eliminar .

Luego, cree un nuevo recurso, res / menu / notes.xml , para configurar la barra de acción para
La actividad que aloja nuestro NoteFragment :

<? xml version = "1.0" encoding = "utf-8"?>


<menu xmlns: android = "http://schemas.android.com/apk/res/android" >
<artículo

721

https://translate.googleusercontent.com/translate_f 15/22
24/2/2020 Tutorial # 14 - Guardar notas

Página 16

T utorial # 14 - S AVING N OTES

android: id = "@ + id / delete"


android: icon = "@ drawable / ic_delete_white_24dp"
android: showAsAction = "ifRoom | withText"
android: title = "@ string / delete" >
</item>
</menu>

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / res / menu / notes.xml )

Esto simplemente define un único elemento de barra de acción, con una ID de eliminación .

Para hacer esto, los usuarios de Android Studio pueden hacer clic derecho sobre el directorio res / menu / y
elija Nuevo> "Archivo de recursos del menú" en el menú contextual. Complete notes.xml en el
Cuadro de diálogo "Nuevo archivo de recursos de menú" y haga clic en Aceptar. Pegue el XML que se muestra arriba en
ese archivo

Si lo prefiere, puede ver el contenido de este archivo en su navegador web a través de este GitHub
enlace.

Para que Android sepa que nuestro NoteFragment desea participar en la barra de acción,
Necesitamos llamar a setHasOptionsMenu (verdadero) en algún momento. Agregar un onCreate ()
Método para NoteFragment para manejar esto cuando se crea el fragmento:

@Anular
public void onCreate ( Bundle savedInstanceState ) {
súper . onCreate ( savedInstanceState );

setHasOptionsMenu ( verdadero );
}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / NoteFragment.java )

Eso activará una llamada a onCreateOptionsMenu () , que tendremos que agregar a


Nota Fragmento :

@Anular
public void onCreateOptionsMenu ( Menú de menú , menú Inflador de menú ) {
inflado . inflar ( R . menú . notas , de menú );

súper . onCreateOptionsMenu ( menú , inflador );


}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / NoteFragment.java )

Esto simplemente infla nuestro nuevo recurso para usar en el menú de opciones.

722

https://translate.googleusercontent.com/translate_f 16/22
24/2/2020 Tutorial # 14 - Guardar notas

Página 17

T utorial # 14 - S AVING N OTES

Si el usuario toca ese botón de la barra de herramientas, se llamará a onOptionsItemSelected () , entonces


necesitaremos agregar eso también a NoteFragment :

@Anular
public boolean onOptionsItemSelected ( elemento MenuItem ) {
si ( elemento . GetItemID () == R . ID . borrar ) {
editor . setText ( nulo );

retorno ( verdadero );
}

return ( super . onOptionsItemSelected ( item ));


}

Aquí, si el usuario tocó nuestro elemento de la barra de acciones de eliminación , borramos el Texto de edición
widget

Paso 14: Cerrar el NoteFragment cuando se elimina


Sin embargo, al tocar ese elemento de la barra de acción, se mantiene el NoteFragment en la pantalla. Eso
podría ser bueno volver automáticamente al libro. sin embargo, el
Nota: el fragmento en sí no sabe cómo hacerlo, como otra cosa (en este caso,
NoteActivity ) ponga el NoteFragment en la pantalla. Por lo tanto, necesitamos pasar el
Solicite cerrar el NoteFragment junto con la parte correspondiente.

Podríamos usar otro objeto de evento y nuestro EventBus . En este caso, lo haremos
demostrar otro enfoque: usar el patrón de contrato para alertar al hosting
actividad que las notas deben estar cerradas.

Defina una interfaz interna en NoteFragment , denominada Contract , de la siguiente manera:

interfaz publica
contrato de interfaz {
nulo closeNotes ();
}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / NoteFragment.java )

Puede poner esas líneas inmediatamente después de la clase pública NoteFragment ...
línea, antes de la declaración de cualquiera de los miembros de datos o métodos, por ejemplo.

Luego, agregue un método privado getContract () , que transmite la Actividad de alojamiento al


Interfaz de contrato :

723

https://translate.googleusercontent.com/translate_f 17/22
24/2/2020 Tutorial # 14 - Guardar notas

Página 18

T utorial # 14 - S AVING N OTES

Contrato privado getContract () {


return (( Contrato ) getActivity ());
}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / NoteFragment.java )

Lo que estamos haciendo aquí es hacer cumplir que la actividad que aloja nuestro NoteFragment
debe implementar la interfaz NoteFragment.Contract .

Luego, agregue una llamada a closeNotes () en el Contrato a nuestra lógica en


onOptionsItemSelected () :

@Anular
public boolean onOptionsItemSelected ( elemento MenuItem ) {
si ( elemento . GetItemID () == R . ID . borrar ) {
editor . setText ( nulo );
getContract (). closeNotes ();

retorno ( verdadero );
}

return ( super . onOptionsItemSelected ( item ));


}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / NoteFragment.java )

Ahora, cuando el usuario hace clic en el elemento de la barra de acción Eliminar , borramos el Texto de edición y
Solicite la actividad de alojamiento para deshacerse de nosotros. En el camino, se llamará a nuestro onStop () ,
haciendo que también borremos el contenido de la columna de prosa en nuestra fila de la base de datos.

En este punto, NoteFragment debería parecerse a:

paquete com . Commonsware . empublita ;

importar android.app.Fragment ;
importar android.os.Bundle ;
importar android.text.TextUtils ;
importar android.view.LayoutInflater ;
importar android.view.Menu ;
importar android.view.MenuInflater ;
importar android.view.MenuItem ;
importar android.view.View ;
importar android.view.ViewGroup ;
importar android.widget.EditText ;
import org.greenrobot.eventbus.EventBus ;
import org.greenrobot.eventbus.Subscribe ;

724

https://translate.googleusercontent.com/translate_f 18/22
24/2/2020 Tutorial # 14 - Guardar notas

Página 19

T utorial # 14 - S AVING N OTES

import org.greenrobot.eventbus.ThreadMode ;

NoteFragment de clase pública


NoteFragment extiende Fragment {
interfaz publica
contrato de interfaz {
nulo closeNotes ();
}

Private static final String KEY_POSITION = "posición" ;


editor privado de EditText = nulo ;

estática NoteFragment newInstance ( int posición ) {


NoteFragment frag = new NoteFragment ();
Bundle args = new Bundle ();

args . putInt ( KEY_POSITION , posición );


frag . setArguments ( args );

volver ( frag );
}

@Anular
public void onCreate ( Bundle savedInstanceState ) {
súper . onCreate ( savedInstanceState );

setHasOptionsMenu ( verdadero );
}

@Anular
pública Vista onCreateView ( LayoutInflater de inflado ,
ViewGroup container ,
Paquete salvadoInstanceState ) {
Ver resultado = inflador . inflar ( R . diseño . editor , contenedor , falsa );

editor = ( EditText ) resultado . findViewById ( R . ID . editor );

retorno ( resultado );
}

@Anular
public void onStart () {
súper . onStart ();

EventBus . getDefault (). registrarse ( esto );

if ( TextUtils . isEmpty ( editor . getText ())) {


DatabaseHelper db = DatabaseHelper . getInstance ( getActivity ());
db . loadNote ( getPosition ());
}

725

https://translate.googleusercontent.com/translate_f 19/22
24/2/2020 Tutorial # 14 - Guardar notas

Página 20

T utorial # 14 - S AVING N OTES

@Anular
public void onStop () {
DatabaseHelper . getInstance ( getActivity ())
. updateNote ( getPosition (),
editor . getText (). toString ());

EventBus . getDefault (). anular el registro ( esto );

súper . onStop ();


}

@Anular
public void onCreateOptionsMenu ( Menú de menú , menú Inflador de menú ) {
inflado . inflar ( R . menú . notas , de menú );

súper . onCreateOptionsMenu ( menú , inflador );


}

@Anular
public boolean onOptionsItemSelected ( elemento MenuItem ) {
si ( elemento . GetItemID () == R . ID . borrar ) {
editor . setText ( nulo );
getContract (). closeNotes ();

retorno ( verdadero );
}

return ( super . onOptionsItemSelected ( item ));


}

@SuppressWarnings ( "sin usar" )


@Subscribe ( threadMode = ThreadMode . MAIN )
public void onNoteLoaded ( evento NoteLoadedEvent ) {
if ( event . getPosition () == getPosition ()) {
editor . setText ( evento . getProse ());
}
}

private int getPosition () {


return ( getArguments (). getInt ( KEY_POSITION , -1));
}

Contrato privado getContract () {


return (( Contrato ) getActivity ());
}
}

726

https://translate.googleusercontent.com/translate_f 20/22
24/2/2020 Tutorial # 14 - Guardar notas

Página 21

T utorial # 14 - S AVING N OTES

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / NoteFragment.java )

NoteActivity ahora debe implementar NoteFragment.Contract e implementar


closeNotes () . Modifique NoteActivity para que se vea así:

paquete com . Commonsware . empublita ;

importar android.app.Activity ;
importar android.app.Fragment ;
importar android.os.Bundle ;

clase pública NoteActivity


Nota La actividad extiende la actividad
implementa NoteFragment . Contrato {
implementos
public static final String EXTRA_POSITION = "posición" ;

@Anular
public void onCreate ( Bundle savedInstanceState ) {
súper . onCreate ( savedInstanceState );

si ( getFragmentManager (). findFragmentById ( androide . R . de id . de contenido ) == nula ) {


int position = getIntent (). getIntExtra ( EXTRA_POSITION , -1);

if ( posición > = 0) {
Fragmento f = Nota Fragmento . newInstance ( posición );

getFragmentManager (). beginTransaction ()


. añadir ( androide . R . de id . de contenido , f ). commit ();
}
}
}

@Anular
public void closeNotes () {
terminar ();
}
}

(de EmPubLite-AndroidStudio / T14-Database / EmPubLite / app / src / main / java / com / commonsware / empublite / NoteActivity.java )

Esto agrega la palabra clave implements y la implementación closeNotes () , que


solo finaliza NoteActivity , devolviendo el control a EmPubLiteActivity .

Si ejecuta esto en un dispositivo o emulador, y va a las notas, verá nuestro


Eliminar el botón de la barra de herramientas:

727

https://translate.googleusercontent.com/translate_f 21/22
24/2/2020 Tutorial # 14 - Guardar notas

Página 22

T utorial # 14 - S AVING N OTES

Figura 293: El nuevo elemento de la barra de acción

Al tocar ese botón de la barra de herramientas se borrará la nota y se cerrará la actividad, devolviéndote
al libro

En nuestro próximo episodio ...


... permitiremos que el usuario comparta las notas de un capítulo con otra persona.

728

https://translate.googleusercontent.com/translate_f 22/22

También podría gustarte