2015-03-16 6 views
1

У меня есть процедура обработки контура, которая пылающая быстро. Он в основном отображает форму в событии OnPaint и обновляется очень быстро ... в основном так же быстро, как вы можете перемещать мышь. Я был очень доволен этим. Он основан на этой работе:Почему этот Android-код так медленно?

http://paulbourke.net/papers/conrec/

Однако я ее портировали на Android/Java и целевой очень быстрый планшет (Nexus 9), и это удивительно медленно, до того момента, когда я чувствую, что я должен быть используя неправильный подход. В основном я:

1) создать представление программно, 2) реализовать метод OnDraw назвать свой класс cContourPlot метод Draw, который 3) перебирает массив данных в 2-D, сравнивает с 1-D «закромах «array» и делает несколько тысяч вызовов функции «DrawPolygonRegion», которую я написал ниже.

Это занимает удивительно долгое время, примерно в 100 раз медленнее, чем в .NET., До такой степени, что мне интересно, что я делаю что-то неправильно. Конкретные вопросы:

a) Является ли функция ниже регулируемой скорости? Есть ли более быстрый способ рисовать полигон, чем использовать Path? (в .NET есть функция DrawPolygon, пришлось сделать что-то новое для порта Android) b) Нужно ли мне что-то делать для «пакетной» моей команды рендеринга? Например (воображаемый :) Canvas.SuspendUpdates, Canvas.ResumeUpdates? c) Нужно ли активировать двойную буферизацию или что-то еще? Мои быстрые исследования говорят, что это делается автоматически в Android, но не уверен. (Мне пришлось активировать его в .NET, но не уверен, что мне нужно здесь)

Большое спасибо за любую проницательность/помощь.

void DrawPolygonRegion(Canvas c, int color, double ... p) 
{ 
    int length = p.length; 

    if (length >= 6) 
    { 
     paint.setColor(color); 
     paint.setStyle(Style.FILL); 
     Path path = new Path(); 
     path.moveTo((float) p[0], (float) p[1]); // used for first point 
     path.lineTo((float) p[2], (float) p[3]); 
     path.lineTo((float) p[4], (float) p[5]); 

     int idx = 6; 

     for (int n=6; n<length; n+=2) 
     { 
      path.lineTo((float) p[n], (float) p[n+1]); 
     } 

     c.drawPath(path, paint); 
    } 
} 
+2

Используйте Traceview и определите, где лежит ваша проблема. – CommonsWare

+1

Единственное, что я хотел бы сделать, это заменить «Path path = new Path()» на 'path.rewind()' или (чуть медленнее) 'path.reset()'. Храните объект «путь» глобальным в области класса. Это предотвращает создание или удаление тысяч объектов «Путь»/сбор мусора. Не уверен, что это самая большая причина, но это вкладчик. – DeeV

ответ

4

Вызов этого несколько тысяч раз. О да, у тебя проблемы.

1) Он выделяет новый Путь. Выделения быстро складываются на Android. Старайтесь избегать их. Предпочитают повторно использовать объекты, особенно в таких функциях, как onDraw.

2) В любом случае, вы все равно не должны создавать целые пути - они лучше сохраняются и повторно используются в режиме добавления.

3) Downcasting from double to float не является бесплатным. Извините, но

4) Вы делаете это прямо на экране Canvas? Не. Сделайте это с помощью растрового холста в своем потоке и выложите результаты на экранное полотно.

Я действительно сомневаюсь, что этот код быстро вспыхивает даже в .NET на ПК с лучшим процессором и оперативной памятью. Я думаю, ваш прикладом сохраняется там с помощью аппаратного ускорения.

+0

1) попробует это и отчитается, (2) не понимают, что полигоны могут менять каждую краску, поэтому система кеширования не сильно поможет ... но что вы имеете в виду «режим добавления»? (3) попробует это и отчитается (4) попробует это, не думайте, что знаете пример или ключевые слова для поиска? (hw accel), это прекрасно, но почему это не аппаратное ускорение, так же помогающее мне здесь? – Chris

+0

Кстати, по сравнению с .NET ...GDI-рендеринг в WinForm, как правило, быстро растет, потому что это тонкая оболочка в той же подсистеме, которая используется ОС и всеми другими приложениями. Вы не будете делать намного лучше, не обходя OS. Я полагал, что использование onDraw и представления будет аналогичным - тот же API, который использует сам Android (в том числе оптимизированный для ускорения HW, двойная буферизация, все эти хорошие вещи), поэтому очень быстро. Это было плохое предположение? Есть ли другая технология или API, которые я должен использовать? – Chris

+0

Это сам API Android. Но это не дает вам все это (в этом случае в Windows GDI-функции не была версия или две задние окна). Не говоря уже о более низких ресурсах. Если вы рисуете тысячи полигонов на фрейм, эти вещи выше должны помочь, но вам, вероятно, придется переместиться в openGL. –

Смежные вопросы