Activity with backgroundthread, not innerclass, communication - android

Hey all, this will contain a few questions since I don't seem to really get it.
I have 1 class, the activity. which should display informations.
Then I have a background thread, extends runnable, which keeps getting new data (there for I didn't use AsyncTask, I could use it as a service, but since I hold a some critical resources in it, I would like not have it released when exiting the activity thread)
But I am in great doubt how to communicate between these 2.
First I thought of Intent, but these seem to be used mostly for launching other activities, or alike, and I need something permanent, since data will be in a steady flow.
Then I found out handler, but this doesn't seem to work when my thread is not an innerclass, so I'm thinking about either going back to the old Java observer pattern, if it's not possible to somehow pass the handler to the outerclass.
Any thoughts would be greatly appreciated
Sincerely
Anders Metnik

There is a mechanism for your case - it is called handlers. Read more here.
As for having thread as inner class:
Create your thread as a separate class, add a constructor with a handler parameter and pass it from your activity.

Thread is not suppose to live outside Creator Activity Context, especially you want to preserve it out of Activity, better use Service (and manage the thread) to hold those data.
Intent is the best in terms of communicating between contexts. I think one of the scenario you can adopt is like this:
Application-class: holds those 'permanent' data you mentioned
Service-class: Work (background) and send out "intents" to signal the update state of the operations
Activity-class: Intent Receiver. Whenever intent signal received, grab the necessary data from the Application-class.

Related

Using context in an AsyncTask via a Fragment that has no UI

I have previously had my App working with just activities and am now working on converting to fragments in order to improve the UI.
Previously my Activity started an AsyncTask and passed in itself to be used as the Context when certain methods required it (not UI operations, but calls to shared preferences and content providers). I have now learnt that this approach can lead to undesirable outcomes if the Activity is destroyed and garbage collected, but it did compile and run fine.
I began this change because I wanted to make my loading screen behave better when the app was paused and stopped. I realised people frown on loading screens in Android but for me it is required as I have an operation that will take 20 seconds or so and that needs to be completed before the app will function.
So using this guide, I began improving my app.
In short the guide moves the AsyncTask into a Fragment that does not have an attached UI, with a separate Fragment for displaying the loading screen with ProgressBar. This means that the Fragment that spawns the AsyncTask does not have a Context, meaning I cant pass one in to the AsyncTask.
As I said before I have operations in the AsyncTask that require a Context object, so where can I get it from? Should I just pass in that data to the AsyncTask before I start?
As far as I know, the context is not a static property, so you actually need one object to retrieve it.
Thus, you can either go the "hack-way" as in this post:
Static way to get 'Context' on Android?
or you can follow Android guidelines and use a Service for your background loading. Remember that AsyncTask is an utility class designed to help in background operations that later need to communicate with the UI, so you should use AsyncTask in correlation with a UI object.
If you, instead use a Service, then you got no problem, since the Service object itself is the context that you need.
If your AsyncTask is not handling any UI components you can use the parent Activity's context. So where you previously passed in this you'll now pass in getActivity(). Note, if you do have it changing the ui this will set you up for Null Pointer Exceptions.

How to have one AsyncTask for all my db calls

I am looking for the right way of designing my app here.
I have 5 activities and each one calls a separate DB method (update, insert, delete ..etc).
I was wondering, instead of creating 5 asynctask classes, each is a private class belonging to the activity to be called from, is there way I can create one asynctask class so I instantiate its object in all the activities?
In C++, you can pass "an entire method" to be executed so Ican create an assign task and pass a method to it to be executed, but I am not sure I can do that in Java. Or what would be the best practice in your mind?
Thank you
Check the Runnable class.
A Runnable represents a task that can be executed. You need to implement it's run() You can pass an instance of Runnable to your AsyncTask and execute it in it's doInBackground(...) method.
There might be a better way to do this, but this is the only thing that is comming to my mind right now.
I'm not sure if this would fit your bill but I would recommend creating an IntentService, that would automatically and asynchronously queue up your Database/Content-Provider read and writes.
You can write separate read, write and update methods that will be handled in the onHandleIntent method of the IntentService. The Intent service insures that
the database/CP access is done asynchronously
successive database/CP access requests are automatically queued and handled
the Service is stopped/started automatically, no need to manage the lifecycle
the database/CP read/write is done even if the app goes into the background
For ListView/Adapter access, consider using loaders

Posting on the UI thread from a singleton manager class

I have a singleton manager class that is called from Activities (UI thread), then it operates on a different thread (Network) and in the it end should call a callback method in the calling Activity.
I was wondering what is the best way to call the callback methods on the UI thread.
I an familiar with the options (see http://android-developers.blogspot.co.il/2009/05/painless-threading.html)
So I was thinking of two options:
the first:
The calling Activities will implement an Interface with a getActivity() method. that method will be used to call Activity.runOnUiThread(Runnable).
the second:
MainApplication, which inits the manager singleton, will pass a Handler instance that belongs to the UI thread.
What is the better option?
I'm also happy to hear any other suggestions
Regardless of what option you choose, you have to keep in mind that the activities have a certain lifecycle, and unlike your singleton class can be finished or moved to the background. In light of this, you should consider again whether singleton is really the best choice here: if it needs to interact with an activity, maybe the activity should manage its lifecycle. If it doesn't depend on any particular activity, you might want to make it a service and send out broadcasts to notify about progress, etc.
What exactly are you trying to do?

Pattern for reusing Android AsnycTask over several Activities?

I have several Activity subclasses in my project, each calling a SOAP based web service, processing and displaying the results. The SOAP serialization, the call handling and the parsing of result into various POJO objects is encapsulated in the MyWebService class. This class executes the actual web service call(s) via an AsyncTask.
For being able to pass back the results to the calling Activity subclass, I figured I enforce that all these activities should implement a WebServiceResultProcessor interface, defining a single function (processWebServiceResults) acting as a callback for the AsyncTask, called from onPostExecute.
I also want to display a ProgressDialog during the web service call. And here comes my question. For being able to display the ProgressDialog (either from MyWebService or it's AsyncTask), I need to pass a reference to the caller Activity's Context. And for being able to execute the callback function from the AsyncTask, I also need to pass the same object reference, but this time as a WebServiceResultProcessor. This seems to me a code smell, passing the same object twice, but can't see any way around that. Instead of interfacing, I could create a new base class, extending the Activity class and enforce inheritance from the extension class, but that would mean I'd exclude ListActivity and the likes from using this MyWebService class.
Is there a better way to do this?
+1, a nice question!
This is not a direct answer on your question. However let me say I think AsyncTask is not a right choice for such stuff. I think so because in this case AsyncTask holds a reference to an Activity (via ProgressDialog instance or the callbacks to be called from onPostExecute()).
Just imagine: in Android the OS may kill the Activity before AsyncTask executes its doInBackground(). This is, of course, some sort of a corner case, but it isn't impossible. Consider a scenario: user gets an incoming call, your activity becomes invisible, the OS needs some more RAM and thus it decides to kill your activity. A memory leak case, at least.
I don't know why Google literally hides the info on how UI should be properly separated from background tasks. Yes, they say "use a Service". But it is not a trivial undertaking. It's a pity Google provides nice guides to almost every development topic, but not on this one. Nevertheless I can suggest to check the "Google I/O 2010 - Android REST client applications" presentation for inspiration. Looks like they gave a key on how such things should be done in Android.
You may have a look into this blog article (part 1 and part 2), which implements a web service with AsyncTaskLoader and the same web service with a Service component. Furthermore it shows the differences between both approaches and there are also interesting comments to the article.
Despite Arhimed's warning, I ended up using AsyncTask, as it still fits my purposes. I just make sure that all Activities calling web services, upon their onDestroy(), send a cancel() to the invoked AsyncTask. The AsyncTask implementation itself gracefully handles the cancel request by checking isCancelled() everywhere where necessary.
As for the original question, I must have had a lapse - the solution is really simple. I pass the Activity subclass instance as an Object to the AsyncTask, and cast it to either Context or to WebServiceResultProcessor, as necessary. Fragments showing how it works:
if (callerActivity instanceof Context) {
ProgressDialog dialog = new ProgressDialog((Context)callerActivity);
}
...
if (callerActivity instanceof WebServiceResultProcessor) {
((WebServiceResultProcessor)callerActivity).processWebServiceResults(soapObject);
}

How to extend an existing background thread solution?

I am using Eclipse to develop an Android application that plots Bluetooth data.
I am using open source code, which has an existing solution that I want to extend and not replace to solve my development problem as stated above.
The open source code has a very nice and solid background thread that among other things continually logs BluetoothData to logcat even when I switch to a new activity.
Currently I have a solution which I am concerned about: I simply leverage a background thread method that writes to logcat to call a static plotData() method in my Plotting Activity. The result seems good. I get a nice plot. It clips along in real-time. Looks like an oscilloscope.
But I have received negative feedback about using the existing background thread coupled with a static method to plot the BluetoothDate. It has been suggested that I use a new thread, or add a handler, or use Async Task, or AIDL to solve my problem.
I have looked at all these solutions without success. Nothing seems to work like my static plotData() method. That is to say the existing background thread calls my static plotData() method which results in a real-time plot that looks great.
But I am still concerned about the negative feedback. I simply want to extend my existing background thread solution which I have done by having it call a static method to plot the data.
What are the problems I might face with this approach? Thread safety? Deadlock? I don't know.
Why do people keep suggesting that I create a new thread, handler, Async Task, or Service to solve my problem when extending my existing thread to call a static method seems to work just fine?
Any suggestions? What are the problems with extending the existing thread to use a static method to plot the data in real-time?
Anyone who says that you should use AIDL for this is a loon who should not be listened to. :) Also someone saying you need a Service if you don't want to have your background thread running when the user is not viewing your activity.
I'm not sure what you mean by "writes to logcat to call a static plotData()." You should write to logcat only for testing. Writing to logcat doesn't cause a call to any Java method.
If you are calling a static plotData() method on your Activity, you need to be extremely careful with this: first because it is difficult to figure out what activity instance should be called from there (it may go away at any time from the user finishing it, or be recreated as a new instance when the configuration changes, etc); and second because you can't touch your app's UI/view hierarchy from a background thread without risking that you corrupt its state (since the view hierarchy is single threaded).
The general model one does for this kind of thing is to have a background thread doing some work, generating the next data to display. Once it is done with the work you send a message to the main thread to have it display the new data. AsyncTask can be a simple way to do this, it takes care of the underlying message sending and threading. You can also implement this yourself, at some point having a Handler that you post a Runnable on or send a Message to that once executed on the UI thread will update your view state.
(Of course if you are using a SurfaceView, the whole point of that is to allow drawing to it outside of the main UI loop, so your background thread could just draw directly on to it as needed. Basically that is like writing a game.)

Categories

Resources