Обновление пользовательского интерфейса из фонового потока с использованием собственного кода полностью (без JNI)? - PullRequest
5 голосов
/ 29 декабря 2011

Я пишу приложение для Android, которое выполняет большую часть обработки в фоновом потоке. Расчеты выполняются в собственном коде с использованием C ++. Я хочу обновить пользовательский интерфейс с частичными результатами во время расчетов.

Я могу сделать это через JNI, а именно установить ссылку на объект пользовательского интерфейса в Java, а затем вызвать метод этого объекта из нативного кода через JNI. Я ищу более эффективное решение без каких-либо вызовов JNI в части рендеринга (базовая настройка и точка входа активации должны быть в java).

Можно ли полностью изменить поток выполнения из фона в пользовательский интерфейс в собственном коде без использования JNI (только в части рендеринга)?

Спасибо за ваши ответы. Очень признателен.

EDIT: Я рассматриваю возможность использования OpenGL для визуализации рассчитанного контента (вроде видеокадров) в моем представлении. В этом случае я бы, вероятно, хотел бы использовать метод eglSwapBuffers(), который доступен в библиотеке EGL начиная с версии 2.3. Я думаю, что самая большая проблема заключается в том, как легко переключиться с фонового потока «вычислений» на поток «открытых GL» пользовательского интерфейса в собственном коде без затрат JNI. Чтобы вы посоветовали? Спасибо за вашу помощь!

ПСЕВДОКОД: Вот некоторый псевдокод, который помогает проиллюстрировать, чего я хочу достичь здесь. Это больше похоже на многопоточность, но в игру вступает и Android-фреймворк.

// background thread
void Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz)
{
    //long calculation
    struct result * res = calculate();

    //want to update ui using opengl on ui thread
    updateGL(res);
}


//want to run it on ui thread as opengl can be run only on ui thread
void updateGL(struct result * res)
{
    //some opengl code with "res"
    someGLcodeWithResult(res);

    //render surface
    eglSwapBuffers();
}

РЕДАКТИРОВАТЬ 2: Поскольку щедрость медленно приближается, еще одно уточнение. Есть несколько способов вызвать метод updateGL выше. Наиболее типичным является использование GLSurfaceView в коде Java. Для этого потребуется установить средство визуализации ( setRenderer () ), а затем переопределить onDrawFrame с некоторым кодом для вызова JNI / собственного уровня. Таким образом, для каждого визуализируемого кадра выполняется один вызов JNI.

Я бы хотел сделать рендеринг немного по-другому. Я хочу вызвать updateGL без использования кода java / JNI вообще и использовать только нативный уровень (как представлено в приведенной выше выдержке). Самая большая проблема для меня сейчас заключается в том, как запустить updateGL в потоке пользовательского интерфейса (требуется OpenGL) без обратного вызова Java. Это вообще возможно?

Ответы [ 4 ]

2 голосов
/ 04 января 2012

Предлагаю взглянуть на источник Mozilla Fennec. Существует минимальная оболочка Java / JNI, которая позволяет выполнять рендеринг на Android, но вся работа выполняется с помощью собственного кода (обычный старый код Mozilla)

1 голос
/ 03 января 2012

Прекрасные мысли, но попытайтесь понять это

  1. У вас есть код на C ++ на нативном
  2. Пользовательский интерфейс в Java работает в VM

Сейчасто, что вы спрашиваете, - это код C ++ для взаимодействия с пользовательским интерфейсом в Java VM, который является еще одной программой для взаимодействия.Единственный способ сделать это - межпроцессное взаимодействие.Сказав это, теперь поймите, что подходит вам лучше всего.JNI быстр и надежен, так как вы не хотите идти по этому пути, найдите любой другой IPC, который вам подходит.

0 голосов
/ 06 января 2012

Я столкнулся с той же проблемой прямо сейчас.Возможно, это может помочь:

Когда вы смотрите на STABLE-APIS.html в последнем NDK, он говорит:

> V. Устойчивые собственные API-интерфейсы Android-9:

Все перечисленные ниже API-интерфейсы доступны для разработки собственного кода, работающего на системных образах Android> 2.3 и выше.

Графическая библиотека EGL:

EGL предоставляет собственный интерфейс платформы для выделения иуправлять поверхностями OpenGLES.Для получения дополнительной информации о его функциях см .:

http://www.khronos.org/egl

В двух словах, это позволит вам сделать следующее непосредственно из собственного кода:

- List supported EGL configurations
- Allocate and release OpenGLES surfaces
- Swap/Flip surfaces for display  (eglSwapBuffers)

Так что если выориентируясь на Android-9, вы можете попробовать использовать EGL lib в нативном коде.(Дайте мне знать, если это работает:))

0 голосов
/ 29 декабря 2011

Можно ли полностью изменить поток выполнения с фона на пользовательский интерфейс полностью в собственном коде без использования JNI?

Вы не можете изменять виджеты из собственного кода.

...