I have strictly separated the layers between different parts of my Android application.
At some point of execution I am updating my data from xml service on Internet. That updating takes up about 10 seconds and is done completely in the background - meaning the user interface of an application works fine. However further calls to my class (later - DataManager) which is responsible for data updating (after update has been started but not yet finished) makes my application crash. NullPointerException is thrown with objects which NEVER are null.
So I assume that only one Thread can use my DataManager at one time and calls to DataManager from other threads ends up in exceptions.
I tried various combinations of putting 'synchronized' keywords near sensitive methods but it seems that when update is executing - NOTHING can use ANYTHING from my DataManager.
BTW other classes which are related to DataManager during the execution also seem to hold null objects.
I guess I am just missing some kind of design pattern which is used to deal with concurrency problems and maybe anyone can suggest me something?
I had trouble dealing with using the Apache http client because of threading issues and I think your issue could be similar in that respect. What I ended up doing was setting up a callback scheme. This may or may not work for you, of course.
This may seem a bit Rube Goldberg-like to you, but it worked for me.
I would have my UI thread call my data manager object with a method that spawned a thread to go and acquire the data. The method's return value is an object that would EVENTUALLY have the data in it. I would have my activity extend an interface, something like "DataCallbackInterface", with a method that the thread would call after it acquired the data (i.e. the last line in run()). Since that call will inherently be within another thread, you'll need to use a Handler to run anything useful in your implementation of the DataCallbackInterface method. When that method is called, you will know for a fact that the data is there and not rely on any strange synchronization flags to get it right.
Related
I'm using an app that uses async tasks to do short term background calculation jobs. These seem to end OK (go through onPostExecute() etc), but in the Eclipse debugger, one or more still hangs around.
Then I found this link - AsyncTask threads never die - so OK, it's about a thread pool and in theory not an issue.
Problems is however, I am also trying to use Google in-app billing code V3, and that appears to throw an exception whenever you carry out a purchase and there's already an AsyncTask thread hanging around. Catching the exception won't help - it still won't do anything.
How can I get around this? What do I need to do to guarantee the old calculation thread(s) have gone?
Found out what is going on here, and it wasn't what I thought. I'll detail it here as it may be useful to somebody. Has nothing to do with other AsyncTask threads and thread pooling.
In the IabHelper class are two functions flagStartAsync() and flagEndAsync(). The aim of these is to produce a single pass gate (bit like wait() and signal() in traditional multi-threading) so only one async operation (that is, communications with Google Play and the server) can occur at a time. If flagStartAsync() get called while something is already going on, it produces an exception. Not terribly graceful, but effective I guess.
The flagStartAsync() 'test and set' gets called at the start of launchPurchaseFlow() among other places, and flagEndAsync gets called in handleActivityResult() - again - among other places. So providing the purchase flow does something that always produces a result, no problem. The problem is - it doesn't always.
If you look at launchPurchaseFlow() there are several paths out that will not kick off the async operation, and if one of those get taken, mAsyncInProgress (the relevant flag) gets left set.
What blew it in my case was that I hadn't checked that the item was already purchased, and 'already purchased' is one of the paths out. Mea culpa, but the problem is that I cannot convince myself that there aren't several other paths that you just cannot avoid at times. What if operation is slow and the 'purchase' button gets pressed twice, for instance? I bet there are others as well. One could catch the exception, and that would stop a crash, but it wouldn't really help if nothing came along to clear the flag in the end. I guess the exception handler could call flagEndAsync() but it has an uncomfortable 'sledgehammer to crack a nut' feel.
It strikes me that this is probably a non-robust piece of code. What I've done for now is call flagEndAsync() in the various ways out of launchPurchaseFlow(), but that is just a temporary fix. I don't know enough about the IabHelper code, but I think it needs more careful thought and I need to analyse it to see everything it does.
Can a thread trying to access the same part of memory at the same time as another thread cause textViews on an android to freeze? if so what is the solution?
The solution is in the design of Android. The method calls to change something in the appearance of a TextView must be called within the Android-UI Thread. You get an exception, if you call methods like TextView.setText() from another thread.
The proposed solution for this is to call Activity.runOnUiThread() or similar and pass your changes to the runnable. See the Android guide about multithreading for more information and the different possiblities.
I never read about View' Thread safety concept in android Documentation. But i guess you will get exception because Changing by two Thread at a time is not good user experience. My conclusion is View are Thread safe and always be updated in UI thread.
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 is 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.
hi im wanting to stop all threads when my main activity closes as some are still running afterwards and are giving NullPointerException as they try to access ArrayLists which no longer exist. however none of the obvious methods are working and they are also deprecated. is it possible as im currently using a try/catch statement as a workaround but would prefer a fix.
TIA
ng93
You need to have your MainActivity tell your threads that it's time to end. You could do this with some sort of value that each thread checks before they access the ArrayLists. Or you could live with the try/catch workaround. But there aren't any good, safe ways of killing threads, which is why those methods got deprecated.
Here's scenario:
Client makes remote call to the service (returns void) and provides
a callback object
Service executes some long running logic on the background thread
and then uses callback object to trigger ether success or failure
which (since these manipulate visual elements) execute in
Activity#runOnUiThread block
The scenario runs fine. The question is - can I use AsyncTask to make
code less verbose (how?) and would be there any advantages in doing it
that way?
Or should I just get away from client callbacks alltogether and
execute remote service calls retrofitted to return some value within
AsyncTask#doInBackground?
It is difficult to say whether AsyncTask will make things less verbose, since we don't know the verbosity of your current implementation.
For me, AsyncTask means I don't have to worry about cleaning up threads myself (e.g., post some sort of kill job to a LinkedBlockingQueue my background thread is waiting on). It also eliminates the custom Job classes I used to create for using with LinkedBlockingQueues. And, it simplifies a bit doing final work back on the UI thread.
In your case, with a remote service, the UI thread issue is less critical, since the activity needs to handle that itself.
I don't see what the difference is between your #2 and your last paragraph. In both cases, your service will call the callback object, which will use something like runOnUiThread() to arrange for the work to be done on the UI thread.
AFAIK, the only two ways to have a service doing any sort of asynchronous work let the client know that work is done is by a broadcast Intent or a callback object. Broadcast Intents are convenient but public (i.e., other code can watch for them).
I suspect I probably have not helped much here, but I just don't know enough of your scenario to provide greater detail.
I'm having quite the same question : i'm developping a map activity, with a 'lazy-loading' functionnality (xml from Network, parsing it, then updating my map with the 'items' created from that parsing...)
i wondered what would be 'the best' way to implement it...
async service launched from a thread, an update notification via Intent?
just a thread (no service, since i don't need to expose it to other applications) w/ callback
asyncTask with callback
i'm comparingthese in terms of speed, using the Android SDK performance analysis Tool traceview
I guess a more precise answer might be found from Android contributors on the Android-developper-group...