开发者

Android runOnUiThread - how to pass the Activity

开发者 https://www.devze.com 2023-04-05 16:58 出处:网络
I\'m writing a XMPP Client using SMACK. So when I want to update my contactList - the ListAdapter.notifyDataSetChanged requires to be run in the UI thread, but obviously the SMACK Library uses Multit

I'm writing a XMPP Client using SMACK.

So when I want to update my contactList - the ListAdapter.notifyDataSetChanged requires to be run in the UI thread, but obviously the SMACK Library uses Multithreading on the RosterListener (which in fact is a good thing). But here is the problem: to run s.th. in the UI thread, I need a valid context.

But how do I get it? Passing the Context of the Activity down to the register function of the RosterListener was the first that came to mind - but I have some functions in different classes there before I even get to the register function, and I don't really like it to pass the context over and over again until it finally reaches its destination, where it will be used.

I guess, I'm not the only one, who has encountered this problem, so how would you solve it?

Maybe a Singleton, just to save this one Context (in my opinion an even less favourable idea...) Or i开发者_如何学Gos maybe my whole design flawed? Is there a possibility to get the UI thread from anywhere?

Bottom line: I don't really have a clue how to handle it, at the moment I'm passing the context as argument through multiple functions, but is there a better way to do it.

Thanks for any help.


Put XMPP code into Service and then send broadcasts. Interested Activities can simply register for those broadcasts. That way you'll never again worry about UI thread and availability of Activity context.


I found a neater and more modular way of doing it. For this you need to have defined an Application Context. Once you have that, you can call RunOnUIThread from any class library without the mess of having a reference to the Activity.

From anywhere within your class library call:

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

Please bear in mind that this is written in C# as I use MonoDroid, but I believe it is very similar to Java. For how to create an ApplicationContext look at this thread


I do not get what exactly you try to do but if you are in some thread and you want to shitch back to UIThread than

Looper is your solution http://developer.android.com/reference/android/os/Looper.html


Reading you, I get a feeling like you are working with callbacks. Smack or whatever that is is calling you back from a worker thread, and you want to post to the main UI thread when that happens.

In my experience, callbacks can always be associated to a custom piece of data, which you pass when registering the callback, and receive when you are actually called back.

In your context there are two approaches which I consider to be poor design:

  • using any kind of global thingy, call it a singleton if you like
  • let your Model expect and return the (Android-and-UI-specific) Context

Instead, I would create a small interface which is implemented by the Activity, have the Model accept an instance of this interface, and yes pass it over the different layers until registration.

The methods exposed by this interface will be called asynchronously, which you could document appropriately, to indicate that runOnUiThread() or similar must be used.

This way, you're not exactly passing the Context (which is a platform and UI detail) all over the place and into the Model. Plus, you avoid global/static data, which leads to various problems, conflicts and other memory leaks.

0

精彩评论

暂无评论...
验证码 换一张
取 消