Android runOnUiThread - как пройти активность - PullRequest
2 голосов
/ 15 сентября 2011

Я пишу XMPP-клиент, используя SMACK.

Поэтому, когда я хочу обновить свой contactList - ListAdapter.notifyDataSetChanged должен запускаться в потоке пользовательского интерфейса, но, очевидно, библиотека SMACK использует многопоточность вRosterListener (что на самом деле хорошо).Но вот проблема: запустить с.т.в потоке пользовательского интерфейса мне нужен действительный контекст.

Но как мне его получить?Передача контекста действия в функцию регистра RosterListener была первой, что пришло в голову - но у меня есть некоторые функции в разных классах, прежде чем я даже доберусь до функции регистрации, и мне не очень нравится ее передаватьконтекст снова и снова, пока он, наконец, не достигнет своего места назначения, где он будет использоваться.

Думаю, я не единственный, кто столкнулся с этой проблемой, так как бы вы решили ее?

Может быть, Singleton, просто чтобы сохранить этот контекст (на мой взгляд, еще менее благоприятная идея ...) Или, может быть, весь мой дизайн имеет недостатки?Есть ли возможность получить поток пользовательского интерфейса из любого места?

Итог: у меня нет ни малейшего понятия, как его обрабатывать, в данный момент я передаю контекст в качестве аргумента через несколько функций, ноЕсть ли лучший способ сделать это.

Спасибо за любую помощь.

Ответы [ 4 ]

1 голос
/ 11 июня 2013

Я нашел более аккуратный и более модульный способ сделать это. Для этого вам необходимо определить Application Context. Если у вас есть это, вы можете вызывать RunOnUIThread из любой библиотеки классов, не имея при этом ссылки на Activity.

Из любого места в вашей библиотеке классов звоните:

Handler handler = new Handler(Application.Context.MainLooper);
handler.Post(() => doStuff());

Пожалуйста, имейте в виду, что это написано на C #, так как я использую MonoDroid, но я считаю, что это очень похоже на Java. Чтобы узнать, как создать ApplicationContext, посмотрите на этот поток

1 голос
/ 15 сентября 2011

Поместите код XMPP в Сервис, а затем отправьте широковещательные сообщения.Заинтересованные действия могут просто зарегистрироваться для этих передач.Таким образом, вы больше никогда не будете беспокоиться о потоке пользовательского интерфейса и доступности контекста Activity.

0 голосов
/ 15 сентября 2011

Читая тебя, я чувствую, что ты работаешь с обратными вызовами. Smack или что-то еще вызывает вас обратно из рабочего потока, и вы хотите публиковать сообщения в основном потоке пользовательского интерфейса, когда это происходит.

По моему опыту, обратные вызовы всегда могут быть связаны с пользовательским фрагментом данных, который вы передаете при регистрации обратного вызова и получаете при фактическом обратном вызове.

В вашем контексте есть два подхода, которые я считаю плохим дизайном:

  • используя любую глобальную вещь, назовите ее одиночной, если хотите
  • пусть ваша Модель ожидает и возвращает контекст (специфичный для Android и пользовательского интерфейса)

Вместо этого я хотел бы создать небольшой интерфейс, который будет реализован в Activity, попросить Модель принять экземпляр этого интерфейса и передать его через разные уровни до регистрации.

Методы, предоставляемые этим интерфейсом, будут вызываться асинхронно, что вы можете соответствующим образом задокументировать, чтобы указать, что необходимо использовать runOnUiThread () или аналогичный.

Таким образом, вы точно не передаете Контекст (который представляет собой платформу и детали пользовательского интерфейса) повсеместно и в Модель. Кроме того, вы избегаете глобальных / статических данных, что приводит к различным проблемам, конфликтам и другим утечкам памяти.

0 голосов
/ 15 сентября 2011

Я не понимаю, что именно вы пытаетесь сделать, но если вы в какой-то теме и хотите вернуться к UIThread, чем

Looper - ваше решение http://developer.android.com/reference/android/os/Looper.html

...