我正在使用SMACK编写XMPP客户端。
因此,当我想更新我的contactList时 - ListAdapter.notifyDataSetChanged需要在UI线程中运行,但显然SMACK Library在RosterListener上使用多线程(实际上这是一件好事)。但问题在于:运行s.th.在UI线程中,我需要一个有效的上下文。
但我怎么得到它?将Activity的Context下传到RosterListener的寄存器函数是我想到的第一个 - 但是在我进入寄存器函数之前,我在不同的类中有一些函数,我真的不喜欢它通过上下文一遍又一遍,直到它最终到达目的地,在那里使用它。
我想,我不是唯一一个遇到过这个问题的人,那你怎么解决呢?
也许是一个单身人士,只是为了保存这一个上下文(在我看来是一个更不利的想法......) 或者也许我的整个设计存在缺陷? 是否有可能从任何地方获取UI线程?
底线:我真的不知道如何处理它,目前我正在通过多个函数传递上下文作为参数,但是有更好的方法来实现它。
感谢您的帮助。
答案 0 :(得分:1)
将XMPP代码置于服务中,然后发送广播。感兴趣的活动可以简单地注册那些广播。这样你就再也不用担心UI线程和Activity上下文的可用性了。
答案 1 :(得分:1)
我找到了一种更整洁,更模块化的方式。为此,您需要定义Application Context
。完成后,您可以从任何类库中调用RunOnUIThread
,而无需引用Activity
。
从您的类库调用中的任何位置:
Handler handler = new Handler(Application.Context.MainLooper);
handler.Post(() => doStuff());
请记住,这是用C#编写的,因为我使用的是MonoDroid,但我相信它与Java非常相似。 有关如何创建ApplicationContext,请查看此thread
答案 2 :(得分:0)
我不知道你到底想要做什么,但是如果你在某个线程而且你想回到UIThread而不是
Looper是你的解决方案 http://developer.android.com/reference/android/os/Looper.html
答案 3 :(得分:0)
读你,我感觉你正在使用回调。 Smack或其他任何东西都是从工作线程调用你的,并且你想在发生这种情况时发布到主UI线程。
根据我的经验,回调总是与自定义数据相关联,您在注册回调时会传递这些数据,并在实际回叫时接收。
在您的上下文中,我认为有两种方法是设计不佳:
相反,我会创建一个由Activity实现的小接口,让Model接受此接口的实例,然后将其传递到不同的层,直到注册。
此接口公开的方法将被异步调用,您可以对其进行适当的记录,以指示必须使用runOnUiThread()或类似方法。
这样,您并没有完全将Context(这是一个平台和UI细节)传递到整个地方并进入模型。另外,您可以避免全局/静态数据,从而导致各种问题,冲突和其他内存泄漏。