Я разрабатываю небольшое приложение, которое читает на определенных html-страницах, переформатирует их и затем показывает их в WebView. Если я запустил свой код в потоке графического интерфейса, то поражение производительности близко к незначительному по сравнению с простое, чтобы WebView отображал исходную html-страницу. Но если я хороший мальчик и люблю, как мне сказали, я должен использовать AsyncTask для запуска кода в фоновом режиме, чтобы не замерзать графический интерфейс в течение этих 3-5 секунд, мой код выполняет свою работу, Проблема в том, что... если я это сделаю, код займет более 10 раз. Для отображения страницы требуется 60 секунд, что неприемлемо.
Отслеживая проблему, TraceView показывает мне, что мой AsyncTask (по умолчанию приоритет) работает примерно в 10 мс кусков, около 4 раз в секунду. Мне нужно установить приоритет потока в MAX_PRIORITY, чтобы приблизиться к допустимым временам загрузки, но даже тогда он занимает 3-4 раза дольше, чем когда я запускаю в потоке графического интерфейса.
Я делаю что-то неправильно или это так, как это работает? И должен ли он работать таким образом...?
Здесь компилируемый код в соответствии с запросом:
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/info/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...
}
}
Чтобы выполнить точно тот же код в моем классе FilterX при запуске как AsyncTask, как при запуске в потоке GUI, я лишил все материалы ProgressBar, а затем получаю следующие тайминги:
- 30+ секунд для загрузки страницы по приоритету по умолчанию
- 15+ секунд для загрузки страницы в MAX_PRIORITY
- 5+ секунд для загрузки страницы при запуске в потоке графического интерфейса пользователя