Devolver datos de AsyncTask Android
Traté de referir la misma pregunta en SO, pero no recibió ayuda.
En mi aplicación para Android, estoy planeando implementar cotización reciente que el usuario ha visitado, es decir, similar a las páginas visitadas recientemente en la web.
- Cómo eliminar una fila en la primera posición de la sqlite en android
- ¿Cuán cuidado debo tener con el hilo de seguridad al crear métodos / actividades que interactúan con la base de datos SQLite?
- Un simple ejemplo androide de Córdova incluyendo Sqlite leer / escribir y buscar
- Comprobación de Android cuando se actualizó la última vez
- en un Listview en el artículo de la lista chasquido ¿cómo puedo conseguir el título (el nombre) del artículo seleccionado? androide
Los siguientes son los pasos que estoy siguiendo:
1.) Siempre que el usuario abra cualquier vista de empresa, obtenga los símbolos de la empresa de la base de datos
2.) A continuación, almacene el símbolo actual junto con dateTime en la base de datos.
3.) Para todos los símbolos obtenidos de la base de datos, Buscar su current value
y %Change
y mostrar Nombre de la empresa, valor actual y% Cambio en una lista.
El problema surge en la clase ASyncTask
como método postExecute
no permite que su tipo de retorno sea diferente de void
.
¿Estoy haciendo algo mal?
Cualquier ayuda será salvavidas!
String[] rsym,rcmp,rchg; rdbM = new RecentDBManager(CompanyView.this); try { Calendar date1 = Calendar.getInstance(); SimpleDateFormat dateformatter = new SimpleDateFormat( "dd/MM/yyyy HH:mm:ss"); String currentdate = dateformatter.format(date1.getTime()); rdbM.openDB(); //STEP 1 rsym = rdbM.getRecent_sym(); //STEP 2 rdbM.setData(currentsymbol, currentdate); rdbM.closeDB(); } catch (Exception e) { throw new Error(" *** ERROR in DB Access *** "+ e.toString()); } //STEP 3 for(int i=0;i<rsym.length;i++) { DownloadRecentQuote quotetask = new DownloadRecentQuote(); recentquotetask .execute(new String[] { "http://abc.com/stockquote.aspx?id=" + rsym[i] }); //CURRENT VALUE and %CHANGE which should be returned from ASyncTask class rcmp[i]=valuearr[0]; rchg[i]=valuearr[1]; } list1 = new ArrayList<HashMap<String, String>>(); HashMap<String, String> addList1; for (int i = 0; i < limit; i++) { addList1 = new HashMap<String, String>(); addList1.put(RecentSym_COLUMN, rsym[i]); addList1.put(RecentCMP_COLUMN, rcmp[i]); addList1.put(RecentChg_COLUMN, rchg[i]); list1.add(addList1); RecentAdapter adapter1 = new RecentAdapter( CompanyView.this, CompanyView.this, list1); listrecent.setAdapter(adapter1); } private class DownloadRecentQuote extends AsyncTask<String, Void, String> { /* Fetching data for RecentQuote information */ @Override protected String doInBackground(String... urls) { String response = ""; for (String url : urls) { DefaultHttpClient client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); try { HttpResponse execute = client.execute(httpGet); InputStream content = execute.getEntity().getContent(); BufferedReader buffer = new BufferedReader( new InputStreamReader(content)); String s = ""; while ((s = buffer.readLine()) != null) { response += s; } } catch (Exception e) { e.printStackTrace(); } } return response; } @Override protected void onPostExecute(String result) { arr1 = result.split("@"); if (arr1[0].length() != 0) { if (arr1[0].equals("1")) { arr = arr1[1].split(";"); //RETURN 2 STRINGS String valuearr[]; valuearr[0] = arr[3]; valuearr[1] = arr[6].concat("%"); //return valuearr; } } }
- No puede ver datos Sqlite con adaptador simple
- Android: Guardando valores booleanos en una base de datos (Principiante)
- Base de datos no visible en la carpeta DDMS cuando se utiliza el dispositivo real en lugar del emulador
- Cómo personalizar FTS tokenizer en Android
- ¿Qué desencadena SqliteDbOpenHelper onUpgrade ()?
- OnItemClick da el índice / la posición del elemento en la página visible ... no el índice real del elemento en la lista .. emitir al habilitar setTextFilterEnabled
- ¿Cómo puedo ver el contenido de un sqlite db de mi aplicación en un dispositivo real?
- Consulta de mejores prácticas de SQLite para Android
PostExecute () no puede devolver un valor, ¿por qué o hacia qué? Su método original que invocó el AsyncTask se ha ido porque su AsyncTask se está ejecutando en el fondo. Es un significado asincrónico cuando AsyncTask.execute () devuelve que todavía se está ejecutando en segundo plano, y por lo tanto postExecute () no puede devolver un valor porque no hay nada para devolverlo.
En su lugar, su AsyncTask necesita una referencia de nuevo a su actividad o algún otro objeto para que pueda publicar sus valores de nuevo a ella. En su código las líneas después de llamar a execute () no pueden estar allí porque su tarea no ha terminado. En su lugar, debe crear un método denominado updateSymbol (currentPrice, percentChange), mover todo ese código debajo de execute (), y en su AsyncTask debe pasar una referencia a la Activity. A continuación, llame a updateSymbol (currentPrice, percentChange) del método onPostExecute ().
Pero, tenga cuidado si tiene una referencia a una actividad que puede ser destruida mientras su doInBackground () se está ejecutando, y cuando postExecute () se ejecuta sólo debe dejar caer los resultados o no intentar actualizar la interfaz de usuario. Por ejemplo, el usuario gira su teléfono causando que la actividad sea destruida. Creo que es mejor mantener una referencia a AsyncTask en la actividad por lo que puede cancelar () si la actividad se destruye. Puede llamar a AsyncTask.cancel () y luego verificar si su tarea se canceló como:
public void postExecute( String result ) { if( !isCanceled() ) { // do your updating here activity.setSymbol( result ); } }
Es muy fácil crear una clase base para todas las actividades para que pueda realizar un seguimiento de AsyncTasks en ejecución:
public class BaseActivity extends Activity { List<AsyncTask> runningTasks; public void onStop() { for( AsyncTask task : runningTasks ) { task.cancel(true); } } public AsyncTask start( AsyncTask task ) { runningTasks.add( task ); return task; } public void done( AsyncTask task ) { runningTasks.remove( task ); } }
Algunos punteros rápidos. No es necesario ejecutar (new String [] {"blah" + blah}). Varargs en Java le permiten hacer esto. Ejecutar ("bla" + bla). Usted también está cogiendo excepciones y continuando sin realmente manejarlas. Será difícil cuando algo realmente sucede porque su aplicación los atrapa, y simplemente continúa como si nada hubiera pasado. Si recibe un error, es posible que desee proporcionar algunos comentarios al usuario y dejar de intentar ejecutar ese proceso. Detener, mostrar un error al usuario, y dejar que hagan lo siguiente. Mueva los bloques de captura a la parte inferior de los métodos.
Esencialmente, AsyncTask.onPostExecute () es donde se hace lo que se quiera hacer después de ejecutar DoInBackground () de AsyncTask y se devuelve el resultado de la ejecución. Esto debe considerarse la mejor práctica.
Cuando se llama a AsyncTask (). Execute () desde el subproceso de UI (nota que este método debe llamarse desde el subproceso de UI), el framework de Android crea un subproceso de trabajo y comienza a ejecutar lo que escribió en AsyncTask.doInBackground () en este trabajador hilo. En este punto (después de llamar a AsyncTask (). Execute ()), el subproceso de interfaz de usuario continúa ejecutando código después de nuevo AsyncTask (). Execute (). Así que ahora durante el tiempo de ejecución, tiene dos subprocesos (interfaz de usuario y subproceso de trabajo) que se ejecutan simultáneamente.
¿Pero dónde y cuándo se devuelve el resultado de la ejecución de AsyncTask del hilo de trabajo al subproceso de UI?
El punto donde su hilo de trabajo (doInBackground ()) termina y devuelve al subproceso de UI es AysncTask.onPostExecute (). Este método está garantizado para ser llamado por el marco en el hilo de interfaz de usuario tan pronto como AsyncTask termina. En otras palabras, no nos importa dónde y cuando AsyncTask.onPostExecute () se llama en tiempo de ejecución, sólo tenemos que garantizar que se llamará en última instancia en algún momento en el futuro. Esta es la razón por la que este método no devuelve un resultado de ejecución, sino que requiere que el resultado de la ejecución se pase como el único parámetro del método de doInBackground ().
Además, la API de Android proporciona una forma de devolver un resultado de ejecución AsyncTask en el tiempo de codificación, AsyncTask.get () :
MyAsyncTask myAsyncTask = new MyAsyncTask(); // This must be called from the UI thread: myAsyncTask.execute(); // Calling this will block UI thread execution: ExecutionResult result = myAsyncTask.get();
Tenga en cuenta que AsyncTask.get () bloqueará la ejecución del subproceso de llamada y probablemente obtendrá una excepción ANR si lo llama en el subproceso de UI. Esta es la carga útil de usar AsyncTask.get (), llamándolo en el subproceso de UI, está haciendo que su AsyncTask (subproceso de trabajo) se ejecute de forma síncrona con el subproceso de UI (haciendo que la interfaz de usuario quede en espera). Para resumir, esto es factible pero no recomendado.
Sólo para referencia futura, porque este post es un poco viejo:
He creado una clase de actividad que tiene un método onStart () y una clase separada para el AsyncTask. Basado en mi prueba, después del método doInbackground () el resultado será enviado a la actividad primero y después de que onPostExecute () se ejecutará. Esto se debe a que basado en logcat, tengo mis primeros datos de respuesta (enviados por el servidor) primero, entonces esta respuesta se mostrará de nuevo de la actividad y el último el mensaje en onPostExecute () se mostrará.
Código de la actividad:
@Override protected void onStart() { super.onStart(); String str = "***"; if(isConnectedToInternet()){ myAsyncTask.execute(); try { if(myAsyncTask.get()) str = myAsyncTask.getResponseMsg(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (CancellationException e) { e.printStackTrace(); } } Log.i("Data returned by server2:", str); }
Código AsyncTask:
public class MyAsyncTask extends AsyncTask<Void, Void, Boolean> { private URL url; private HttpURLConnection conn; private String strResponseMsg; public MyAsyncTask(String url) throws MalformedURLException{ this.url = new URL(url); } @Override protected void onPreExecute() { Log.i("Inside AsyncTask", "myAsyncTask is abut to start..."); } @Override protected Boolean doInBackground(Void... params) { boolean status = false; try { conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(Manager.ConnTimeout); conn.setReadTimeout(Manager.ReadTimeout); int responseCode = conn.getResponseCode(); Log.i("Connection oppened", "Response code is:" + responseCode); if (responseCode == HttpURLConnection.HTTP_OK) { BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); if (in != null) { StringBuilder strBuilder = new StringBuilder(); // Read character by character int ch = 0; while ((ch = in.read()) != -1) strBuilder.append((char) ch); // Showing returned message strResponseMsg = strBuilder.toString(); Log.i("Data returned by server:", strResponseMsg); status = true; } in.close(); } } catch (IOException e) { e.printStackTrace(); } return status; } @Override protected void onPostExecute(Boolean result) { Log.i("Inside AsyncTask", "myAsyncTask finished its task. Returning data to caller..."); } public String getResponseMsg(){ return strResponseMsg; } }
- Android Packager: java.util.zip.ZipException: entrada duplicada: classes.dex
- Tabulaciones de la barra de herramientas de Android y enfoque del teclado