Estoy desarrollando una pequeña aplicación que lee en páginas html específicas, las reformatea y luego las muestra en una WebView. Si ejecuto mi código en el hilo de la GUI, el impacto en el rendimiento es casi despreciable comparado con simplemente dejar que WebView muestre la página html original. Pero si soy un buen chico y hago lo que me dicen, se supone que debo usar un AsyncTask para ejecutar el código en segundo plano, para no congelar la GUI durante esos 3-5 segundos mi código hace su trabajo . El problema es ... si lo hago, el código tarda más de 10 veces en terminar. Una página demora más de 60 segundos en mostrarse, lo cual es inaceptable.AsyncTask, ¿debe tomarse un castigo de penalización de rendimiento ...?
Rastreando el problema, TraceView me muestra que mi AsyncTask (en prioridad predeterminada) se ejecuta en trozos de aproximadamente 10 ms, alrededor de 4 veces por segundo. Necesito establecer la prioridad de mi subproceso en MAX_PRIORITY para acercarme a los tiempos de carga aceptables, pero aun así toma 3-4 veces más tiempo que cuando ejecuto el hilo de la GUI.
¿Estoy haciendo algo mal o es así como funciona? ¿Y debe funcionar de esta manera ...?
Aquí es código compilables conforme a lo solicitado:
package my.ownpackage.athome;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class AndroidTestActivity extends Activity
{
WebView webview;
//...
private class HelloWebViewClient extends WebViewClient
{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
AndroidTestActivity.this.fetch(view, url);
return true;
}
}
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// To allow to connect to the web and pull down html-files, reset strict mode
// see http://stackoverflow.com/questions/8706464/defaulthttpclient-to-androidhttpclient
if (android.os.Build.VERSION.SDK_INT > 9)
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
// webview init etc...
fetch(webview, "http://www.example.com");
}
// This one calls either the AsyncTask or does it all manually in the GUI thread
public void fetch(WebView view, String url)
{
//** Use these when run as AsyncTask in background - SLOW!
//** Takes 30+ seconds at default thread priority, with MAX_PRIORITY 15+ seconds
// AsyncTask<Void, String, String> fx = new FilterX(url, view, this);
// fx.execute(); // running as AsyncTask takes roughly ten times longer than just plain load!
//** Use these when not running as AsyncTask - FAST! takes ~5 seconds
FilterX fx = new FilterX(url, view, this);
fx.onPreExecute();
final String str = fx.doInBackground();
fx.onPostExecute(str);
}
}
class FilterX extends AsyncTask<Void, String, String>
{
WebView the_view = null;
// other stuff...
FilterX(final String url, final WebView view, final Activity activity)
{
the_view = view;
// other initialization
// same code in both cases
}
protected void onPreExecute()
{
// same code in both cases
}
protected String doInBackground(Void... v)
{
// same in both cases...
return new String(); // just to make it compile
}
protected void onPostExecute(final String string)
{
the_view.loadUrl(string);
// same in both cases...
}
}
Para ejecutar exactamente el mismo código en mi clase FiltroX cuando se ejecuta como AsyncTask como cuando se ejecuta en el hilo GUI, me desnudé todas las cosas ProgressBar, y luego obtener los siguientes tiempos:
- de 30 segundos para cargar una página en la prioridad de subprocesos predeterminado
- 15+ segundos en cargar una página en MAX_PRIORITY
- 5+ segundos en cargar una página cuando se ejecuta en el hilo GUI
dónde dice TraceView que está gastando la mayor parte de su tiempo al usar la tarea asíncrona? Pasar de 5 segundos a 60 hace que suene como si algo hubiera salido terriblemente mal al volver a diseñar su código. (publique los fragmentos relevantes según sea necesario) – smith324
No hay un verdadero "cambio de factor" en marcha. Simplemente elimino la llamada para ejecutar() y en su lugar llamo a doInBackground() desde el hilo de la GUI. Cortaré las partes relevantes y te mostraré sus trivialidades y muchas dudas de que sea un problema. – OppfinnarJocke
Nunca respondió mi primera pregunta: ¿dónde dice TraceView que está usando su tiempo? – smith324