Оптимизация производительности WebView в Android

webview-opt

В этом материале мы поговорим о том как можно улучшить быстродействие (роизводительность) вашего приложения, игры, которая написана на HTML+CSS+JS и с помощью метода WebView запилена в Андроид.

Любая игра да и современное приложение тоже как известно требуют довольно гладких плавных анимаций (скроллы, появление списка со стороны и тд). Но вот по поводу анимаций в HTML на андроид возникало и возникает по сей день множество споров и неотвеченных вопросов в интернете. Сегодня мы постараемся немного помочь советами как оптимизировать ваше приложение или игру на Андроид написанную на HTML.

1. Используйте CSS анимацию. О том почему и зачем вы прочитаете здесь, где был обзор HTML технологий доставки анимации клиенту.

2. Проверьте валидность вёрстки и убедитесь что все тэги закрыты и всё стоит по своим местам.

3. Оптимизируйте Javascript код в вашем приложении/игре. Если у вас всё завязано на нём, тогда его оптимизация даст вам хороший прирост производительности. Вы можете найти в интернете статьи ою этом. Пока предлагаю только на английском (раз и два). Найдёте хорошие на русском - в комменты! 

4. Попытаемся на нативном уровне Андроида что-нибудь придумать:

4.1. Там где вы объявляете Webview можно добавить 

webview.getSettings().setRenderPriority(RenderPriority.HIGH);
webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

Сами Андроид Девелоперы первый параметр не считают очень успешным появился и кажется действует только в API 19 (Могу ошибаться).

4.2. В манифест в ваше активити можно добавить опцию:

android:hardwareAccelerated="true"

Эта опция призвана делать добро оптимизиции и хардверно ускорять работу что должно плавно сказываться на анимации... Должно... На самом деле этот параметр очень неоднозначен у некоторых он даёт прирост производительности, а у некоторых наоборот всё портит. С техничекого плана данная опция принудительно впускает в процесс обработки всего что происходит на экране мощи видеокарты. Не всегда удаётся как хочется. Именно поэтому нашлись умники, которые копнули это поглубже и как оказалось GPU акселлерация не способна улучшить CSS/JS, поэтому в файл с основной Активити добавляют:

if (Build.VERSION.SDK_INT >= 11){
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

Он вроде как бы отключает на самом WebView акселлерацию и говорят конечной производительность идёт в плюс.

Некоторые предлагают использовать:

mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);

Но по сути этот та же акселлерация. От которой как мы уже поняли в WebView лучше избавиться.

4.3. Попробуйте добавить следующий CSS-код слоям, спискам и пр, что участвует в анимации:

-webkit-transform: translate3d(0,0,0);
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;
-webkit-transform-style: flat;

Некоторым это помогает сделать анимацию более гладкой. В основном бывает достаточно использовать:

transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);

Уверенно включит 3D акселерацию следующий код:

-webkit-transform: translate3d(0,0,0);
-webkit-transform: tranlsateZ(0);
-webkit-transform: scale3d(1,1,1);
-webkit-transform: scale3dZ(1);

Но самое главное не злоупотребите этим. Как оно помогает так оно и может навредить. Добавляйте это свойство только в элементы, которые анимируются.

4.4. Если у вас многое завязано на плавности скролла, то некоторые предлагают использовать вместо стандартного класса WebView этот:

import android.content.Context;
import android.view.MotionEvent;
import android.webkit.WebView;


public class MyWebView extends WebView{

public MyWebView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}

private long lastMoveEventTime = -1;
private int eventTimeInterval = 40;

@Override
public boolean onTouchEvent(MotionEvent ev) {

long eventTime = ev.getEventTime();
int action = ev.getAction();

switch (action){
case MotionEvent.ACTION_MOVE: {
if ((eventTime - lastMoveEventTime) > eventTimeInterval){
lastMoveEventTime = eventTime;
return super.onTouchEvent(ev);
}
break;
}
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_UP: {
return super.onTouchEvent(ev);
}
}
return true;
}
}

Код рассчитан на заимодействие одним пальцем, для двух и больше (мультитач) придётся немного допилить.

5. Не используйте ни в коем случае событие onclick на странице, поскольку это даёт тормоза длинной порядка 300ms. А это разве есть хорошо?

Вместо этого используйте ontouchstart (на элемент нажали, выполняется событие,палец убрали), а если нужно чтобы был именно клик по элементу (на элемент нажали, палец убрали, выполняется событие) тогда напишите по быстрому комбо-обработчик ontouchstart+ontouchend.

6. Не используйте большое DOM древо в коде. Оптимально будет если глубина вложений не будет длиннее 3. Например body > div > ul > li (body естественно не считается в этом числе).

7. Люди советуют в построении HTML страницы приложения и игры использовать там где возможно абсолютные позиции, а также пиксели вместо процентов. Это каким-то образом напрямую связано с обработкой контента CPU и GPU.

8. Могут появляться тормоза если вы не отключили стандартное действие на touch событие. При чём на девайсах от Samsung может вообще останавливаться вся анимация на странице после свайпа или длительного удержания. 

Чтобы отключить это, используйте jQuery (можно маленькую min библиотеку) в которых есть event.preventDefault() и event.stopPropagation() которые как раз и предотвращают стандартные обработки событий. Вместо них советовали использовать return false, но что-то не удалось. Итак, вот что нужно добавить в JS код вашего приложения или игры:

document.addEventListener('touchstart', function(event) {
event.preventDefault();
event.stopPropagation();
/* Здесь ваш код обработки события*/
}, false);

document.addEventListener('touchmove', function(event) {
event.preventDefault();
event.stopPropagation();
/* Здесь ваш код обработки события*/
}, false);

document.addEventListener('touchend', function(event) {
event.preventDefault();
event.stopPropagation();
/* Здесь ваш код обработки события*/
}, false);

9. Старайтесь не использовать большие изображения подгоняя их потом под все размеры. Сделайте лучше для каждого разрешения свой размер. Для этого можно воспользоваться CSS Media Queries. Помните что <div><img src="/my.jpg"></div> медленнее рендериться, чем <div style="background:URL(my.jpg)"></div>. Только в последнем случае надо задавать статичные размеры div'у.

На этом пожалуй всё. Если у вас есть чем дополнить статью - пишите в комментарии. Если вы согласны со способом (или он вам помог) описанным в коментариях - голосуйте.


Добавить комментарий


Защитный код
Обновить

Карта сайта