android - Forma/orden recomendada para leer datos de un servicio web, analizar esos datos e insertarlos en una base de datos SQLite
android-service android-sqlite (3)
Debo comenzar a mencionar que soy totalmente nuevo en Android, acabo de terminar de leer un libro introductorio rápido y ahora tengo que implementar mi primera aplicación. Esta aplicación se utilizará para tomar pedidos. Entre todos los datos que voy a almacenar en una base de datos local, dos tablas son las más importantes: Clientes y Artículos, siendo esta última la más grande de todas las tablas (aproximadamente 20000 registros) Uno de los procesos principales en mi aplicación, busca Todos los datos que mi aplicación necesita para funcionar sin conexión cuando el usuario presiona un botón que inicia las operaciones diarias en el dispositivo.
Bueno, el proceso consta de los siguientes pasos:
a.
Lea un servicio tranquilo para recuperar los datos de los clientes
si.
Analiza la respuesta a objetos Json
C.
Inserte esos clientes en la tabla Clientes
re.
Lea un servicio tranquilo para recuperar los datos de los artículos
mi.
Analiza la respuesta a objetos Json
F.
Inserte esos artículos en la tabla de artículos
Esto es lo que he planeado hacer:
- Escriba una clase auxiliar que maneje todas las solicitudes HTTP GET. Luego llame a esta clase siempre que necesite descargar todos los datos de Clientes y Artículos
- Dado que todo este proceso puede llevar mucho tiempo, necesito hacerlo en segundo plano. Entonces, según algunas sugerencias, voy a poner todo este código dentro de un Servicio enlazado.
- Mientras todo este largo procesamiento se lleva a cabo en segundo plano, tendré que mostrar algún tipo de indicador (un Diálogo de progreso) Esta es la razón por la que opté por usar un Servicio enlazado
Aunque creo que tengo la idea general de cómo hacer la mayoría de estas cosas por separado , creo que poner todo junto es una historia bastante diferente.
Estas son las preguntas que tengo ahora que tengo que armar el rompecabezas:
- ¿Crees que el orden en el que estoy ejecutando los 6 pasos del proceso descrito es correcto / eficiente? Si tuviera que hacer algunos cambios, ¿qué cambiaría?
- Si la actividad que inició el servicio se cancela explícitamente o está oculta por otra actividad, el servicio debe tener una manera de informar al usuario que el proceso ha finalizado. ¿Cómo podría implementar eso?
- ¿Es posible / recomendado escribir en la base de datos SQLite dentro del servicio? ¿Es lo mismo que cuando lo hago dentro de una actividad?
- En J2ME he hecho algo similar, y cuando pongo algo como los 6 pasos que mencioné anteriormente, todos se ejecutan secuencialmente, es decir, uno tras otro. ¿Es lo mismo en Android?
Espero no hacer demasiadas preguntas. Simplemente los puse juntos porque están todos relacionados.
Básicamente, en esta pregunta no estoy pidiendo un código de trabajo (aunque estaría bien si pudieras proporcionar algún código de muestra) Lo que realmente busco son algunas sugerencias, alguna orientación. Algo así como "Oye, creo que esto podría ayudarte con el punto número 3" o "Puede que este artículo te resulte útil" , "Creo que será mejor que uses esto en lugar de eso" . Ese tipo de cosas.
Decidí venir a ti porque son los expertos y realmente necesito que alguien me ponga en la dirección correcta.
Muchas gracias.
PD: Por favor, no cierre esta pregunta, si cree que necesito cambiar algo, avíseme y lo haré.
¿Crees que el orden en el que estoy ejecutando los 6 pasos del proceso descrito es correcto / eficiente? Si tuviera que hacer algunos cambios, ¿qué cambiaría?
Depende. Si estos datos están relacionados y no pueden existir el uno sin el otro, entonces debe cambiar el orden de esta manera:
a. Read a restful service to retrieve the Customers Data
b. Parse the response to Json Objects
d. Read a restful service to retrieve the Articles Data
e. Parse the response to Json Objects
c. Insert those customers to the Customers Table
f. Insert those articles to the Articles Table
Los pasos
c
y
f
deben combinarse en la transacción.
De lo contrario, el orden no importa. Si los datos no están relacionados, sería una buena idea separar estos procesos y ejecutarlos en secuencia.
Si la actividad que inició el servicio se cancela explícitamente o está oculta por otra actividad, el servicio debe tener una manera de informar al usuario que el proceso ha finalizado. ¿Cómo podría implementar eso?
Sugiero comenzar con la implementación de la clase
IntentService
.
Maneja el hilo en segundo plano y funciona como una cola de eventos en los que el
Intent
único entrega datos para procesar.
En realidad, podría implementar uno de los patrones presentados por Google en una de sus
conferencias IO
.
He implementado una opción A que se muestra en el video.
A mí me funciona muy bien.
El truco es que usar
ContentProvider
desde el fondo actualiza automáticamente la interfaz de usuario que escucha los cambios gracias a CursorAdapter.
Para actualizar el progreso de la interfaz de usuario, puede usar
LocalBroadcastManager
o bibliotecas de bus de eventos, por ejemplo,
Otto
.
También puede ampliar sus tablas y almacenar el estado y el progreso, la actualización de las tablas también actualizaría automáticamente la interfaz de usuario, solo tenga en cuenta que estas actualizaciones deberían ser poco frecuentes, por ejemplo, controlar en el fondo del servicio con qué frecuencia se actualiza el progreso de la tabla calculando el progreso primero y verificando con servicio variable local si se cambia.
En caso de que su aplicación esté en segundo plano, publique una notification estado. El usuario debe poder volver a su aplicación haciendo clic en la notificación.
¿Es posible / recomendado escribir en la base de datos SQLite dentro del servicio? ¿Es lo mismo que cuando lo hago dentro de una actividad?
Puedes hacerlo dentro del Servicio. En realidad, si sigues el patrón que he mencionado anteriormente, lo harías en el nivel de procesador en el hilo de servicio en segundo plano.
En J2ME he hecho algo similar, y cuando pongo algo como los 6 pasos que mencioné anteriormente, todos se ejecutan secuencialmente, es decir, uno tras otro. ¿Es lo mismo en Android?
Depende completamente de usted cómo funcionará la comunicación con el servidor.
Si decide usar la clase
IntentService
, funcionará en una secuencia que no es una mala idea en Android.
Por otro lado, puede extender la clase de servicio directamente e implementar su propio ejecutor de subprocesos con un grupo de subprocesos.
También puede tener clases dedicadas de
IntentService
para operaciones no relacionadas.
También recomiendo leer lecciones:
- Transferencia de datos sin agotar la batería
- Transferencia de datos mediante adaptadores de sincronización
Si no desea jugar directamente con la implementación de la conexión HTTP, considere usar Retrofit o Volley
Si solo necesita analizadores JSON, estos 2 son los mejores:
Decidí venir a ti porque ustedes son los expertos
primero
i am not expert
y tampoco
i am not knowledgeable
, puedes encontrar personas más expertas que yo, pero esta
es mi opinión,
hope to give you some help
.
en primer lugar, olvide usar
AsyncTask
para descargar porque debe usarse para trabajos en segundo plano no como el suyo, creo que la cantidad de archivo que desea descargar es bastante grande (creo que sí)
consulte
downloadmanager
de google para ver cómo funciona, puede ayudarlo.
http://developer.android.com/reference/android/app/DownloadManager.html
http://blog.vogella.com/2011/06/14/android-downloadmanager-example/
si desea utilizar el
service
use el
service
unbound service
porque no desea que Android o usuario destruyan el servicio cuando el usuario cierre las aplicaciones, ¿verdad?
Creo que quieres obtener tus datos de cualquier manera.
Para ser eficiente, recomiendo estos pasos:
a. Lea un servicio tranquilo para recuperar los datos de los clientes
si. cuando obtenga los datos del Cliente:
-
crear otro servicio o hilo para leer un servicio tranquilo para recuperar los datos de los artículos
-
Analiza la respuesta a Json Objects en tu antiguo servicio o hilo
ahora tiene 2 servicios o subprocesos que se ejecutan simultáneamente, así que siga los pasos que evidentemente
insert
parse
y así, en cada servicio o subproceso.
¿Por qué no combino ayd? porque creo que al usuario no le gusta esperar mucho tiempo detrás de la barra de progreso de descarga.
para insertar sus datos en la
transaction
uso de la base de datos y le recomiendo que use:
es un
ORM
más eficiente que otros para la base de datos y se libera de la implementación de db.
Si la actividad que inició el servicio se cancela explícitamente o está oculta por otra actividad, el servicio debe tener una manera de informar al usuario que el proceso ha finalizado. ¿Cómo podría implementar eso?
notificación de uso:
http://developer.android.com/training/notify-user/build-notification.html
http://www.tutorialspoint.com/android/android_notifications.htm
http://www.vogella.com/tutorials/AndroidNotifications/article.html
Mientras todo este largo procesamiento se realiza en segundo plano, tendré que mostrar algún tipo de indicador (un ProgressDialog). Esta es la razón por la que opté por usar un Servicio Bound`
¿Cómo puedo actualizar la interfaz de usuario de un servicio independiente?
Utilice un
LocalBroadCastManager
, o en general
BroadCastReciever
IU de actividad de actualización de Android desde el servicio
En J2ME he hecho algo similar, y cuando pongo algo como los 6 pasos que mencioné anteriormente, todos se ejecutan secuencialmente, es decir, uno tras otro. ¿Es lo mismo en Android?
esto depende de sus pasos, si sigue mi idea, corre
concurrently
y si ejecuta su idea, correrá
sequentially
.
Buena suerte.
Hice algo como el tuyo.
En el primer paso obtengo datos del servicio
webservice
en HTTP GET del método POST usando
AsyncTask
esta manera:
public class GetService extends AsyncTask<String, String, String> {
private String mRestUrl;
private ServiceCallback mCallback;
private final HttpClient Client = new DefaultHttpClient();
private String Content;
private String url;
private String Error;
private ProgressDialog barProgressDialog;
private ProgressDialog Dialog;
public GetService(String restUrl, ServiceCallback callback) {
this.mRestUrl = restUrl;
this.mCallback = callback;
this.url = restUrl;
Dialog = new ProgressDialog(AppContext.CurrentContext);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... urls) {
Content = null;
BufferedReader reader = null;
try {
StringBuilder builder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(this.url);
HttpResponse response = client.execute(get);
int status = response.getStatusLine().getStatusCode();
if (status == 200) // sucess
{
HttpEntity e = response.getEntity();
// String data = EntityUtils.toString(e);
InputStream content = e.getContent();
reader = new BufferedReader(new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
Content = builder.toString();
} else if (status == 401) {
return "-Auth Failed Error Code 400";
} else {
return "-Error Code: " + status;
}
} catch (Exception ex) {
Error = ex.getMessage();
} finally {
Dialog.dismiss();
try {
reader.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
return Content;
}
@Override
protected void onPostExecute(String result) {
try {
GetService.this.get(20000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
mCallback.onTaskComplete(result);
super.onPostExecute(result);
}
}
y mi clase de devolución de llamada es:
clase abstracta pública ServiceCallback {
public abstract void onTaskComplete(String result);
}
Llamo a AsyncTask en mi código en todas partes donde quiero obtener datos del servicio web:
new GetService(url, new ServiceCallback() {
public void onTaskComplete(String response) {
// Parse Response of WebService
}
}).execute();
En el segundo paso, analizo la respuesta de WebService en el método onTaskComplete usando bibliotecas auxiliares json como
Gson
o
Jackson
.
por ejemplo en jackson:
List<YourClass> data = new ObjectMapper()
.readValue(
response,
new TypeReference<List<YourClass>>() {
});
Al final almaceno los datos en la base de datos.
para conectarme a DB Prefiero usar
GreenDao
como mi ORM.
De esta manera, los datos de almacenamiento en DB se pueden hacer en un código de línea como este:
//after converting json to object
YourORMDaoClass.insertOrReplaceInTx(data);
Para usar
GreenDao
ORM,
http://greendao-orm.com/
es muy útil;