0% encontró este documento útil (0 votos)
197 vistas35 páginas

Ejemplo XML

El documento describe un archivo XML que contiene datos sobre los mejores hoteles en Roma. El archivo XML tiene una estructura jerárquica con una etiqueta raíz <hoteles> que encierra etiquetas <hotel> para cada uno, las cuales contienen campos como id, nombre, precio, valoración e imagen. El objetivo es crear una aplicación Android que muestre esta información en una lista utilizando el parser XML XmlPullParser para extraer los datos del archivo y mostrarlos.

Cargado por

Marian Ferrer
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
197 vistas35 páginas

Ejemplo XML

El documento describe un archivo XML que contiene datos sobre los mejores hoteles en Roma. El archivo XML tiene una estructura jerárquica con una etiqueta raíz <hoteles> que encierra etiquetas <hotel> para cada uno, las cuales contienen campos como id, nombre, precio, valoración e imagen. El objetivo es crear una aplicación Android que muestre esta información en una lista utilizando el parser XML XmlPullParser para extraer los datos del archivo y mostrarlos.

Cargado por

Marian Ferrer
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd

ARCHIVO XML CON DATOS DE HOTELES

En esta ocasión usaremos datos sobre los mejores hoteles en Roma. La


idea es crear una aplicación Android que proyecte los elementos de cada hotel en
una lista.
Puedes obtener el formato XML desde el siguiente enlace:

[Link]
Si visualizas si contenido verás la siguiente jerarquía XML:

[Link]

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


<hoteles
xmlns:datosWeb="[Link]
roma">
<hotel>
<idHotel>1</idHotel>
<nombre>Nerva Boutique Hotel</nombre>
<precio>145</precio>
<valoracion calificacion="5.0" noOpiniones="420" />
<urlImagen>
[Link]
[Link]
</urlImagen>
<datosWeb:descripcion>
<![CDATA[ El mejor hotel de Roma ]]>
</datosWeb:descripcion>
</hotel>
<hotel>
<idHotel>2</idHotel>
<nombre>Vatican View</nombre>
<precio>155</precio>
<valoracion calificacion="4.5" noOpiniones="230" />
<urlImagen>
[Link]
roma/[Link]
</urlImagen>
<datosWeb:descripcion>
<![CDATA[ Disfruta de la mejores noches en Roma ]]>
</datosWeb:descripcion>
</hotel>
<hotel>
<idHotel>3</idHotel>
<nombre>Barcelo Aran Park</nombre>
<precio>210</precio>
<valoracion calificacion="4.5" noOpiniones="345" />
<urlImagen>
[Link]
roma/[Link]
</urlImagen>
<datosWeb:descripcion>
<![CDATA[ Desayuna con la mejor pizza ]]>
</datosWeb:descripcion>
</hotel>
...
</hoteles>

¿Qué interpretas de la estructura XML?


Por intuición verás un conjunto de datos describiendo varias entidades tipo hotel,
con un formato homogéneo. Donde el propósito de cada etiqueta es el siguiente:

 <hoteles>: Nodo raíz que encabeza que representa al conjunto de


datos.
 <hotel>: hace referencia a una entidad de tipo hotel en particular.
 <idHotel>: Identificador único de cada hotel. Será de utilidad si
deseas usar una base de datos local sqlite para aplicar caching.
 <nombre>: Nombre registrado del hotel como compañía.
 <valoracion>: Representa la popularidad del hotel, la cual es
descrita en los atributos "calificacion" y "noOpiniones". El primero
determina de 1 a 5 la calificación promedio obtenida por la cantidad de
opiniones (segundo) generadas por los usuarios que acceden al servicio
de búsqueda.
 <urlImagen>: Contiene el link de la imagen que representa al hotel
para su promoción.
 <datosWeb:descripcion>: Esta etiqueta representa la descripción de
promoción que existe para el hotel. Le asigne el
namespace "datosWeb" para cubrir el tema de prefijos ahora que
empecemos a parsear. Igualmente incluí la marca CDATA para mostrar
la obtención de este tipo de valor.

CREAR NUEVO PROYECTO EN ANDROID STUDIO

Paso 1. Crea un nuevo proyecto en Android Studio accediendo a File > New >
New Project…  y nómbralo “Guía De Hoteles En Roma”. Añade una
actividad del tipo Blank Activity en el asistente de creación y asígnale el
nombre de [Link].
Paso 2. Este proyecto tiene los siguientes componentes especiales para el
diseño de la interfaz:
 Cards
 Lista con RecyclerView
 Librería Glide para carga de imágenes
Lo que significa que debes modificar las dependencias tú
archivo [Link] de la siguiente forma:

dependencies {
...
compile '[Link]:appcompat-v7:22.2.1'
compile '[Link]:recyclerview-v7:22.2.1'
compile '[Link]:glide:3.6.1'
compile '[Link]:cardview-v7:22.2.1'
}

CÓDIGO PARA PARSEAR ARCHIVO XML


El parsing XML requiere que separes las etiquetas que necesitas de aquellas que
no.

Recuerda que parsear un formato XML significa convertir el flujo de datos con ese
formato a una representación interna de nuestra aplicación. En este caso objetos
Java que cobren significado dentro de la lógica de implementación.

Paso 3. Crea una clase que represente cada hotel del archivo XML
llamada [Link]. Debido a que necesitamos todos los campos de la
etiqueta <hotel>, entonces incluimos una representación de cada etiqueta en la
clase.
[Link]

import [Link];
import [Link];

/**
* Clase que representa cada hotel del archivo XML
*/
public class Hotel {
private String idHotel;
private String nombre;
private String precio;
private float valoracion;
private String urlImagen;
private int noOpiniones;
private String descripcion;

// Proveedor estático de datos para el adaptador


public static List<Hotel> HOTELES = new ArrayList<>();

public Hotel(String idHotel,


String nombre,
String precio,
float valoracion,
String urlImagen,
int noOpiniones,
String descripcion) {
[Link] = idHotel;
[Link] = nombre;
[Link] = precio;
[Link] = valoracion;
[Link] = urlImagen;
[Link] = noOpiniones;
[Link] = descripcion;
}

public int getNoOpiniones() {


return noOpiniones;
}

public String getNombre() {


return nombre;
}

public String getIdHotel() {


return idHotel;
}

public String getPrecio() {


return precio;
}

public String getUrlImagen() {


return urlImagen;
}

public float getValoracion() {


return valoracion;
}

public String getDescripcion() {


return descripcion;
}
}

Las imágenes que usaremos están alojadas en el servidor, pero si deseas


descargarlas para realizar pruebas locales, usa este botón:
DESCARGAR IMÁGENES
Paso 4. Ahora es turno para crear el Parser XML de la aplicación Android. Esto
requiere que usemos la clase XmlPullParser para gestionar el recorrido del
documento.
Pero… ¿Como funciona XmlPullParser?
Pasos a seguir:

1. Crear una clase que controle el flujo de parsing.


2. Implementar un método del parsing general que retorne en los datos
completos.
3. Subdividir en métodos cada uno de los procesamientos de las etiquetas para
reducir complejidad.
La lectura es sencilla. Este parser permite al programador recorrer todo el
documento XML pasando de etiqueta en etiqueta de forma controlada. Esto
permite recorrer toda la jerarquía y decidir en qué momento obtener los valores
que necesitamos.

Si te fijas necesitamos dos ciclos para leer el archivo.

El primero para recorrer todas las etiquetas <hotel> y el segundo para recorrer


los elementos anidados de cada etiqueta.

La clase XmlPullParser basa su comportamiento de lectura en varios tipos de


eventos. Estos nos servirán para usar condiciones que al ser verdaderas, obtengan
los datos que requerimos. Los siguientes son los eventos más importantes:
Tipo de Descripción
evento

START_DOCUMEN
T Este tipo de evento se presenta cuando se inicializa el parser.

Representa el inicio de una nueva etiqueta en el DOM. Esto permite


que leas el nombre de la etiqueta con getName() o los atributos de la
START_TAG etiqueta congetAttributeValue().

Indica que se encontró el valor de la etiqueta y este puede ser leído


TEXT en formato texto. Para ello usa el método getText().

Se da cuando el parser acaba de leer una etiqueta de cierre dentro


de los datos XML. Si deseas obtener el nombre de dicha etiqueta,
END_TAG entonces usagetName().

END_DOCUMENT Indica que el parser acaba de encontrar el final del flujo XML.
Algunos puntos importantes:

 Crear nueva instancia del Parser— Usa el método


estático [Link]() para crear una instancia de XmlPullParser.

XmlPullParser parser = [Link]();

 Indicar el flujo que alimenta al Parser— Invoca el


método setInput(). Este recibe el flujo de datos tipo InputStream . Como
segundo parámetro puedes indicar el encoding del formato, como por
ejemplo formato utf-8.

[Link](inputStream, null);

 Habilita características especiales si es necesario— Cambia


el estado de una característica especial del parser XML con el
método setFeature(). Una de ellas es la capacidad para leer namespaces
con la constante XmlPullParser.FEATURE_PROCESS_NAMESPACES . Por defecto no
está habilitada, así que habilítala si lo necesitas.

[Link](XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
 Obtener el siguiente elemento u evento de parsing— Debido
a que recorremos manualmente el archivo XML, emplea el
método next() para ir al próximo elemento u evento. También puedes
usar nextTag() para este propósito, la diferencia está en que este método
solo retorna un evento si actualmente el parser está
en START_TAG o END_TAG.

 if ([Link]() == [Link]) {
 result = [Link]();
 [Link]();
 }

return result;

 Retorna en el tipo de evento actual en el que se encuentra el


parser— Averigua este dato con el método getEventType().

 if ([Link]() != XmlPullParser.START_TAG) {
 throw new IllegalStateException();

 Comprobar eventos y nombres— Usar el método require() para


saber si el evento actual es del tipo especificado y si el namespace y el
nombre de la etiqueta, coinciden con las características requeridas. Si
no es así, entonces se lanza una excepción.

[Link](XmlPullParser.START_TAG, "prefijo_namespace", ETIQUETA_NOMBRE);

Con estos datos claros, veamos como parsear el archivo XML de hoteles en Roma:

[Link]

import [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

/**
* Parser XML de hoteles
*/
public class ParserXml {

// Namespace general. null si no existe


private static final String ns = null;

// Constantes del archivo Xml


private static final String ETIQUETA_HOTELES = "hoteles";

private static final String ETIQUETA_HOTEL = "hotel";

private static final String ETIQUETA_ID_HOTEL = "idHotel";


private static final String ETIQUETA_NOMBRE = "nombre";
private static final String ETIQUETA_PRECIO = "precio";
private static final String ETIQUETA_VALORACION = "valoracion";
private static final String ETIQUETA_URL_IMAGEN = "urlImagen";
private static final String ETIQUETA_DESCRIPCION = "descripcion";

private static final String PREFIJO = "datosWeb";


private static final String ATRIBUTO_CALIFICACION = "calificacion";
private static final String ATRIBUTO_OPINIONES = "noOpiniones";

/**
* Parsea un flujo XML a una lista de objetos {@link Hotel}
*
* @param in flujo
* @return Lista de hoteles
* @throws XmlPullParserException
* @throws IOException
*/
public List<Hotel> parsear(InputStream in) throws
XmlPullParserException, IOException {
try {
XmlPullParser parser = [Link]();
[Link](XmlPullParser.FEATURE_PROCESS_NAMESPACE
S, true);
[Link](in, null);
[Link]();
return leerHoteles(parser);
} finally {
[Link]();
}
}

/**
* Convierte una serie de etiquetas <hotel> en una lista
*
* @param parser
* @return lista de hoteles
* @throws XmlPullParserException
* @throws IOException
*/
private List<Hotel> leerHoteles(XmlPullParser parser)
throws XmlPullParserException, IOException {
List<Hotel> listaHoteles = new ArrayList<Hotel>();

[Link](XmlPullParser.START_TAG, ns, ETIQUETA_HOTELES);


while ([Link]() != XmlPullParser.END_TAG) {
if ([Link]() != XmlPullParser.START_TAG) {
continue;
}
String nombreEtiqueta = [Link]();
// Buscar etiqueta <hotel>
if ([Link](ETIQUETA_HOTEL)) {
[Link](leerHotel(parser));
} else {
saltarEtiqueta(parser);
}
}
return listaHoteles;
}

/**
* Convierte una etiqueta <hotel> en un objero Hotel
*
* @param parser parser XML
* @return nuevo objeto Hotel
* @throws XmlPullParserException
* @throws IOException
*/
private Hotel leerHotel(XmlPullParser parser) throws
XmlPullParserException, IOException {
[Link](XmlPullParser.START_TAG, ns, ETIQUETA_HOTEL);
int idHotel = 0;
String nombre = null;
String precio = null;
float calificacion = 0;
String urlImagen = null;
int noOpiniones = 0;
String descripcion = null;
HashMap<String, String> valoracion = new HashMap<>();

while ([Link]() != XmlPullParser.END_TAG) {


if ([Link]() != XmlPullParser.START_TAG) {
continue;
}
String name = [Link]();

switch (name) {
case ETIQUETA_ID_HOTEL:
idHotel = leerIdHotel(parser);
break;
case ETIQUETA_NOMBRE:
nombre = leerNombre(parser);
break;
case ETIQUETA_PRECIO:
precio = leerPrecio(parser);
break;
case ETIQUETA_VALORACION:
valoracion = leerValoracion(parser);
calificacion =
[Link]([Link](ATRIBUTO_CALIFICACION));
noOpiniones =
[Link]([Link](ATRIBUTO_OPINIONES));
break;
case ETIQUETA_URL_IMAGEN:
urlImagen = leerUrlImagen(parser);
break;
case ETIQUETA_DESCRIPCION:
descripcion = leerDescripcion(parser);
break;
default:
saltarEtiqueta(parser);
break;
}
}
return new Hotel(idHotel,
nombre,
precio,
calificacion,
urlImagen,
noOpiniones,
descripcion);
}

// Procesa la etiqueta <idHotel> de los hoteles


private int leerIdHotel(XmlPullParser parser) throws IOException,
XmlPullParserException {
[Link](XmlPullParser.START_TAG, ns, ETIQUETA_ID_HOTEL);
int idHotel = [Link](obtenerTexto(parser));
[Link](XmlPullParser.END_TAG, ns, ETIQUETA_ID_HOTEL);
return idHotel;
}

// Procesa las etiqueta <nombre> de los hoteles


private String leerNombre(XmlPullParser parser) throws IOException,
XmlPullParserException {
[Link](XmlPullParser.START_TAG, ns, ETIQUETA_NOMBRE);
String nombre = obtenerTexto(parser);
[Link](XmlPullParser.END_TAG, ns, ETIQUETA_NOMBRE);
return nombre;
}

// Procesa la etiqueta <precio> de los hoteles


private String leerPrecio(XmlPullParser parser) throws IOException,
XmlPullParserException {
[Link](XmlPullParser.START_TAG, ns, ETIQUETA_PRECIO);
String precio = obtenerTexto(parser);
[Link](XmlPullParser.END_TAG, ns, ETIQUETA_PRECIO);
return precio;
}

// Procesa la etiqueta <valoracion> de los hoteles


private HashMap<String, String> leerValoracion(XmlPullParser parser)
throws IOException, XmlPullParserException {
[Link](XmlPullParser.START_TAG, ns,
ETIQUETA_VALORACION);
String calificacion = [Link](null,
ATRIBUTO_CALIFICACION);
String noOpiniones = [Link](null,
ATRIBUTO_OPINIONES);
[Link]();
[Link](XmlPullParser.END_TAG, ns,
ETIQUETA_VALORACION);

HashMap<String, String> atributos = new HashMap<>();


[Link](ATRIBUTO_CALIFICACION, calificacion);
[Link](ATRIBUTO_OPINIONES, noOpiniones);

return atributos;
}

// Procesa las etiqueta <urlImagen> de los hoteles


private String leerUrlImagen(XmlPullParser parser) throws
IOException, XmlPullParserException {
String urlImagen;
[Link](XmlPullParser.START_TAG, ns,
ETIQUETA_URL_IMAGEN);
urlImagen = obtenerTexto(parser);
[Link](XmlPullParser.END_TAG, ns,
ETIQUETA_URL_IMAGEN);
return urlImagen;
}

// Procesa las etiqueta <descripcion> de los hoteles


private String leerDescripcion(XmlPullParser parser) throws
IOException, XmlPullParserException {
String descripcion = "";
[Link](XmlPullParser.START_TAG, ns,
ETIQUETA_DESCRIPCION);
String prefijo = [Link]();
if ([Link](PREFIJO))
descripcion = obtenerTexto(parser);
[Link](XmlPullParser.END_TAG, ns,
ETIQUETA_DESCRIPCION);
return descripcion;
}

// Obtiene el texto de los atributos


private String obtenerTexto(XmlPullParser parser) throws IOException,
XmlPullParserException {
String resultado = "";
if ([Link]() == [Link]) {
resultado = [Link]();
[Link]();
}
return resultado;
}

// Salta aquellos objeteos que no interesen en la jerarquía XML.


private void saltarEtiqueta(XmlPullParser parser) throws
XmlPullParserException, IOException {
if ([Link]() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch ([Link]()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}

El método parsear() es aquel que se encarga de orquestar todo el proceso de


parsing para retornar la lista de hoteles.
El primer bucle while del cual habíamos hablado se encuentra en el
método leerHoteles(), el cual obtiene todos los datos.
Sin embargo este método se sirve de leerHotel(), donde encontraremos el
segundo bloque anidado del que habíamos hablando. Este se encarga de procesar
cada etiqueta dependiendo de su nombre.
El método obtenerTexto() es usado para conseguir el valor de todas las etiquetas.
Dentro de este se comprueba el evento TEXT para obtener el valor con getText().
Finalmente viene una serie de métodos encargados de procesar la toma de datos
de cada etiqueta. También tenemos el método saltarEtiqueta() que se encarga
de ignorar aquellas etiquetas que no deseamos, por si llegase a ocurrir.
Si te fijas, la única etiqueta que tiene un componente CDATA es <descripcion>.
Pero no es necesario usar métodos adicionales para la obtención del valor.
Procesamos su contenido normalmente. Adicionalmente obtuvimos el prefijo de
esta etiqueta con el método getPrefix() y así comparar la validez de esta.

CREAR LISTA CON RECYCLERVIEW Y CARDS

Paso 5. Diseña el layout de los ítems que se mostrarán en la lista. Para ello ve a
la carpeta res/layout y agrega un nuevo documento
llamado item_hotel.xml con la siguiente definición XML.

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


<[Link]
xmlns:android="[Link]
xmlns:card_view="[Link]
android:layout_width="match_parent"
android:layout_height="match_parent"
card_view:cardCornerRadius="4dp"
card_view:cardUseCompatPadding="true">

<RelativeLayout
xmlns:android="[Link]
android:id="@+id/info"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
android:id="@+id/miniatura_hotel"
android:layout_width="match_parent"
android:layout_height="@dimen/altura_miniatura_hotel"
android:layout_alignParentTop="true"
android:background="@color/background_material_light" />

<RatingBar
android:id="@+id/valoracion"
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/nombre_hotel"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:visibility="visible" />

<TextView
android:id="@+id/nombre_hotel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/miniatura_hotel"
android:padding="8dp"
android:text="Nombre del hotel"
android:textAppearance="@style/[Link].S
ubhead"
android:textSize="14sp" />

<TextView
android:id="@+id/precio_actual"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/miniatura_hotel"
android:layout_alignParentEnd="true"
android:padding="8dp"
android:text="Precio"
android:textAppearance="@style/[Link].H
eadline"
android:textColor="@android:color/white" />

<ImageView
android:id="@+id/boton_masOpciones"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:padding="@dimen/padding_boton_icono"
android:src="@drawable/ic_dots_vertical" />

<ImageView
android:id="@+id/boton_favoritos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="@+id/boton_masOpciones"
android:padding="@dimen/padding_boton_icono"
android:src="@drawable/ic_heart" />

</RelativeLayout>

</[Link]>

La idea es mostrar el nombre del hotel, el precio por noche, su valoración, la


imagen que está asociada y dos iconos que representan las acciones de las cards.
Paso 6. Lo siguiente es crear el adaptador para el RecyclerView. El objetivo
de este componente es inflar cada uno de los datos que vienen de la lista de
hoteles.
Así que crea una nueva clase llamada [Link] e incluye el
siguiente código.

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

import [Link];

/**
* {@link [Link]} para poblar
un recycler view
* con información de hoteles.
*/
public class AdaptadorDeHoteles extends
[Link]<[Link]> {

/**
* Interfaz de comunicación
*/
public interface OnItemClickListener {
void onItemClick(ViewHolder item, int position);
}

private OnItemClickListener listener;

public void setOnItemClickListener(OnItemClickListener listener) {


[Link] = listener;
}

public OnItemClickListener getOnItemClickListener() {


return listener;
}

public static class ViewHolder extends [Link]


implements [Link] {
// Campos respectivos de un item
public TextView nombre;
public TextView precio;
public RatingBar valoracion;
public ImageView imagen;

private AdaptadorDeHoteles padre = null;

public ViewHolder(View v, AdaptadorDeHoteles padre) {


super(v);

[Link](this);
[Link] = padre;

nombre = (TextView) [Link]([Link].nombre_hotel);


precio = (TextView) [Link]([Link].precio_actual);
valoracion = (RatingBar) [Link]([Link]);
imagen = (ImageView) [Link]([Link].miniatura_hotel);

@Override
public void onClick(View v) {
final OnItemClickListener listener =
[Link]();
if (listener != null) {
[Link](this, getAdapterPosition());
}
}
}

@Override
public long getItemId(int position) {
return [Link](position).getIdHotel();
}

public AdaptadorDeHoteles() {
}

@Override
public int getItemCount() {
return [Link]();
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = [Link]([Link]())
.inflate([Link].item_hotel, viewGroup, false);
return new ViewHolder(v, this);
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
Hotel item = [Link](i);

[Link]([Link]());
[Link]("$" + [Link]());
[Link]([Link]());
[Link]([Link]())
.load([Link]())
.centerCrop()
.into([Link]);
}

Es fundamental que la carga de las imágenes se realice con la librería


Glide para que no tengas problemas en el hilo principal.
También puedes sobrescribir el método getItemId() para retornar el identificador
de cada elemento. Esto será de gran ayuda a la hora de procesar los eventos del
recycler view.

PARSING XML DESDE URL CON LA CLASE


HTTPURLCONNECTION

Paso 7. Debido a que el formato XML se encuentra en la url que especificamos al


inicio, es necesariousar el cliente HttpUrlConnection para traer su contenido a
la aplicación Android.
Recuerda que las operaciones de red necesitan ser aisladas en un hilo de trabajo a
parte. Lo que significa que primero debemos declarar una AsyncTask dentro
de ActividadPrincipal para realizar la consulta.
Veamos:

private class TareaDescargaXml extends AsyncTask<String, Void,


List<Hotel>> {

@Override
protected List<Hotel> doInBackground(String... urls) {
try {
return parsearXmlDeUrl(urls[0]);
} catch (IOException e) {
return null; // null si hay error de red
} catch (XmlPullParserException e) {
return null; // null si hay error de parsing XML
}
}

@Override
protected void onPostExecute(List<Hotel> result) {
// Actualizar contenido del proveedor de datos
[Link] = result;
// Actualizar la vista del adaptador
[Link]();
}
}

Dentro de doInBackground() retornarmos en el resultado que nos entrega el


métodoparsearXmlDeUrl(). Este recibe la url que viene como parámetro en la
tarea asíncrona, luego descarga el contenido alojado en la url y realiza el parsing
XML.
Es importante el manejo de errores al realizar el parsing y ejecutar la
operación de red.
Finalmente en onPostExecute() se recibe la lista de hoteles con el fin de actualizar
el proveedor de datos [Link]. Esto permite que llames al
método notifyDataSetChanged() del recycler para actualizar la lista.
Paso 8. Procesa la operación Http dentro del método parsearXmlDeUrl().

// Dentro de [Link]
private List<Hotel> parsearXmlDeUrl(String urlString)
throws XmlPullParserException, IOException {
InputStream stream = null;
ParserXml parserXml = new ParserXml();
List<Hotel> entries = null;

try {
stream = descargarContenido(urlString);
entries = [Link](stream);

} finally {
if (stream != null) {
[Link]();
}
}
return entries;
}

private InputStream descargarContenido(String urlString) throws


IOException {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection)
[Link]();
[Link](10000);
[Link](15000);
[Link]("GET");
[Link](true);
// Iniciar la petición
[Link]();
return [Link]();
}

Lo primero es descargar el flujo del archivo [Link] desde la url (declarada


como constante) a través del método descargarContenido().
Luego con el InputStream que resulta de esta acción, podemos inicializar el parser
de hoteles e invocar al método parsear() para retornar en una colección
tipo List<Hotel>.
Con ello ya es posible echar a andar la tarea asíncrona dentro del
método onCreate().

CAMBIAR LA ACTIVIDAD PRINCIPAL

Paso 9. Ve a res/layout y abre el archivo actividad_principal.xml. Ahora


incluye dentro del diseño unatoolbar para representar la action bar de la
actividad principal, junto a un RecyclerView para la lista.

<RelativeLayout
xmlns:android="[Link]
xmlns:tools="[Link]
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ActividadPrincipal">

<!-- Toolbar -->


<[Link]
xmlns:app="[Link]
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/[Link]"
app:theme="@style/[Link]" />

<[Link]
xmlns:android="[Link]
android:id="@+id/reciclador"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/toolbar"
android:padding="3dp"
android:scrollbars="vertical" />

</RelativeLayout>

Paso 10. Modifica la clase ActividadPrincipal para que obtenga la instancia del


recycler view. Luego relaciona el adaptador y un LinearLayoutManager.

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

/**
* Actividad que muestra el parsing XML en una lista
*/
public class ActividadPrincipal extends AppCompatActivity{
private RecyclerView reciclador;
private LinearLayoutManager linearManager;
private AdaptadorDeHoteles adaptador;

private final static String URL =


"[Link]
roma/[Link]";

@Override
protected void onCreate(Bundle savedInstanceState) {
[Link](savedInstanceState);
setContentView([Link].actividad_principal);

usarToolbar();

reciclador = (RecyclerView) findViewById([Link]);


[Link](true);
linearManager = new LinearLayoutManager(this);
[Link](linearManager);

adaptador = new AdaptadorDeHoteles();


[Link](true);
[Link](this);

[Link](adaptador);

new TareaDescargaXml().execute(URL);

}
private void usarToolbar() {
Toolbar toolbar = (Toolbar) findViewById([Link]);
setSupportActionBar(toolbar);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate([Link].menu_principal, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = [Link]();

if (id == [Link].action_settings) {
return true;
}

return [Link](item);
}

private class TareaDescargaXml extends AsyncTask<String, Void,


List<Hotel>> {

@Override
protected List<Hotel> doInBackground(String... urls) {
try {
return parsearXmlDeUrl(urls[0]);
} catch (IOException e) {
return null; // null si hay error de red
} catch (XmlPullParserException e) {
return null; // null si hay error de parsing XML
}
}

@Override
protected void onPostExecute(List<Hotel> result) {
// Actualizar contenido del proveedor de datos
[Link] = result;
// Actualizar la vista del adaptador
[Link]();
}
}

private List<Hotel> parsearXmlDeUrl(String urlString)


throws XmlPullParserException, IOException {
InputStream stream = null;
ParserXml parserXml = new ParserXml();
List<Hotel> entries = null;

try {
stream = descargarContenido(urlString);
entries = [Link](stream);

} finally {
if (stream != null) {
[Link]();
}
}

return entries;
}

private InputStream descargarContenido(String urlString) throws


IOException {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection)
[Link]();
[Link](10000);
[Link](15000);
[Link]("GET");
[Link](true);
// Iniciar la petición
[Link]();
return [Link]();
}
}
Para el recycler view usa el método setHasStableIds() con el valor de true. Esta
acción habilita la obtención de identificadores para los ítems a través del
método getItemId() del adaptador.
Ejecuta el proyecto y verás el siguiente resultado.

CREAR ACTIVIDAD DE DETALLE


Paso 11. Mostraremos la descripción de cada hotel en una actividad nueva que
contenga su detalle. Para ello crea una nueva actividad en Android Studio y
asígnale el nombre de “[Link]”.
Paso 12. Ahora ve a res/layout y abre su archivo de diseño. La idea es añadir
tres bloques de contenido para mostrar la información de cada hotel romano.
El primer bloque será un ImageView que despliegue la imagen del hotel. En
segundo lugar se encuentra un LinearLayout central que mostrará el nombre y
precio.
El último espacio será ocupado con otro LinearLayout para la calificación, el
número de opiniones y la descripción.

Lo que dejaría la siguiente definición XML del layout:


actividad_detalle.xml

<LinearLayout
xmlns:android="[Link]
xmlns:app="[Link]
xmlns:tools="[Link]
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="[Link]
Detalle">

<!-- Toolbar -->


<[Link]
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/[Link]"
app:theme="@style/[Link]" />

<ImageView
android:id="@+id/hotelImageView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="50"
android:scaleType="centerCrop" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?colorPrimary"
android:elevation="2dp"
android:orientation="vertical"
android:paddingBottom="@dimen/margen_estandar"
android:paddingStart="@dimen/especificacion2"
android:paddingTop="@dimen/margen_estandar">

<TextView
android:id="@+id/nombreTextView"
style="@style/[Link]"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:textIsSelectable="true"/>

<TextView
android:id="@+id/precioTextView"
style="@style/[Link]"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginLeft="@dimen/especificacion2"
android:layout_weight="50"
android:elevation="2dp"
android:orientation="vertical"
android:paddingBottom="@dimen/margen_estandar"
android:paddingTop="@dimen/margen_estandar">

<RatingBar
android:id="@+id/calificacion"
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/margen_estandar"
android:layout_marginTop="@dimen/margen_estandar"
android:visibility="visible" />

<TextView
android:id="@+id/noOpinionesTextView"
style="@style/[Link].Body1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/margen_estandar"
android:textIsSelectable="true" />

<TextView
android:id="@+id/descripcionTextView"
style="@style/[Link].Body1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/margen_estandar"
android:textIsSelectable="true" />

</LinearLayout>

</LinearLayout>

Paso 13. Abre la clase ActividadDetalle y modifica su comportamiento con el


fin de actualizar cada view del layout. Usa el método getIntent() para obtener el
intent que vendrá desdeActividadPrincipal. Luego extrae el identificador del
hotel que fue enviado y publica sus datos.

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

import [Link];

public class ActividadDetalle extends AppCompatActivity {

public static final String EXTRA_ID =


"[Link]";
@Override
protected void onCreate(Bundle savedInstanceState) {
[Link](savedInstanceState);
setContentView([Link].actividad_detalle);

usarToolbar();

// Extraer ID
Intent intent = getIntent();
int idHotel = [Link](EXTRA_ID, 0);
Hotel hotelActual = [Link](idHotel);

// Obtener instancias de cada view


TextView nombre = (TextView)
findViewById([Link]);
TextView precio = (TextView) findViewById([Link]);
RatingBar calificacion = (RatingBar) findViewById([Link]);
TextView noOpiniones = (TextView)
findViewById([Link]);
TextView descripcion = (TextView)
findViewById([Link]);
ImageView imagen = (ImageView)
findViewById([Link]);

// Añadir valores del hotel


assert hotelActual != null;
[Link]([Link]());
[Link]("$" + [Link]());
[Link]([Link]());
[Link]([Link]() + " Opiniones");
[Link]([Link]());
[Link](this)
.load([Link]())
.into(imagen);

private void usarToolbar() {


Toolbar toolbar = (Toolbar) findViewById([Link]);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate([Link].actividad_detalle, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = [Link]();
if (id == [Link].action_settings) {
return true;
}
return [Link](item);
}
}

PROCESAR EVENTOS DEL RECYCLERVIEW CON


ONITEMCLICKLISTENER

Paso 14. Haz que la actividad principal herede de la interfaz de


comunicació[Link] e implementa el
controlador onItemClick(). Esto permitirá iniciar la actividad de detalle según el
ítem presionado.

public class ActividadPrincipal extends AppCompatActivity


implements [Link] {

...

@Override
public void onItemClick([Link] item, int
position) {
Intent intent = new Intent(this, [Link]);
int itemId = (int) [Link]();
[Link](ActividadDetalle.EXTRA_ID, itemId);
startActivity(intent);
}

...
}

También podría gustarte