Android callback - is this a potential memory leak? - android

In my Android application, one of my activities includes instantiation of other classes of mine.
Some of the classes need to write to the screen. I want to keep all the layout interaction at the top level.
So, I created an Interface which includes a list of methods that can be called to output to the screen. I then Implement this interface in the main Activity.
Finally, when instantiating the classes I pass "this" to the constructor and it is saved and used for the callbacks.
My question is: is there a danger of memory leaks due to me passing the Activity object itself into one of its objects?

I would look into the standard Android Handler mechanism for this (also supporting custom callbacks for UI changes).
Here's an example of a handler defining a custom callback to handle UI changes :
http://developer.android.com/resources/samples/TicTacToeLib/src/com/example/android/tictactoe/library/GameActivity.html
As long as you can ensure that your "this" is scoped properly, you should be pretty safe, however, as soon as you start passing activities around to other classes, it does leave the door open to potential memory leaks, as pieces of code can get a hold of that instance now and prevent it from being garbage collected in time where garbage collection should have occured on the object.

If I understand your question correctly, you have abstracted some UI interaction functionality in to a class and decorated your activity with it.
The simple answer to your question is no. Although you pass an instance of "this" to the object, the scope of the object itself is governed by Activity. In fact android framework passes around context, not very similar to what you do. I believe we can all agree that Activity has a very limited lifetime.
The second point I wanted to make is, about the whole methodology itself. Android provides mechanism to post back to the main thread to perform UI interactions. (post or asynctask etc..) You should use one of these mechanism to make some changes to UI (in the main thread). So my question is, could you not write an anonymous inner class to perform this operation using asynctask, especially if this functionality is unique only to this Activity.

Related

Grant control of Activity UI in SDK

Currently we're making an Android library that contains an Activity. We want to control the exact flow and the state of the activity, but give the user that implements the library control what the UI looks like. Meanwhile, we want to expose the least amount of internal classes.
The SDK user may decide where views are placed, sizes, colors; we decide on what happens on onClicks and provide the texts of TextViews.
The activity makes use of a Model-View-Intent pattern, so we want to expose the immutable state. Without adjustable UI, the Activity and all its' classes are internal. With adjustable UI, a lot more classes have to made public. This increases the risk of breaking changes on updates and exposes our logic.
To expose the UI, several solution were thought of:
Having a static callback on the activity that calls onCreate(), so setContentView() can be set, and calls render(state: State) on every state change. Our classes are shielded as we like, but using a static for this is questionable.
Make the Activity open, so sdk users can subclass it. This means that every class used by the activity, has to be changed from internal to public.The classes which actually should be internal, will be hidden by obfuscating them with ProGuard.
It would be the nicest to pass a function in the Intent, which to my knowlegde is not possible.
Pass a POJO were we define parameters such as background color, which is the most restricting to the sdk user and is not in consideration.
Which solution is the best? Is there another method than the ones we thought of?
The SDK user may decide where views are placed, sizes, colors; we decide on what happens on onClicks and provide the texts of TextViews.
I picture this like so:
Your consumer receives a State, a ViewGroup, and an Actions object, which I'll explain later.
Based on State the consumer is required to create several views and place them as they wish within supplied ViewGroup.
The consumer is also required to register above views using some Actions.register*Button methods.
The above logic is executed inside one callback method. Once said method finished your SDK will verify correctness (all required actions are assigned a clickable view) and proceed.
Now, how to pass this callback method to sour SDK?
1.
It would be the nicest to pass a function in the Intent
This is actually possible with relative ease (and, IMO, some severe drawbacks).
In your SDK create a static Map<Key, Callback> sCallbacks. When your consumer registers the callback using your API, you'll generate a lookup key for it and store it within the map. You can pass the key around as an Intent extra. Once your SDK activity is opened it can lookup the callback using the key from its intent.
The key can be a String or UUID or whatever fits your needs and can be put inside an intent.
Pros:
It's deceptively easy to implement and use.
The consumer can use your SDK from just one file. All the calling code is in one place.
Cons:
You're not in charge where the callback is created. The consumer may create it as an anonymous class inside an Activity, which results in a memory leak.
You lose the callback map when process dies. If the app is killed while in your SDK activity you need to gracefully handle it when the app is restarted.
Variables are not shared across multiple processes. If your SDK activity and the calling code are not in the same process, your SDK activity will not be able to find the callback. Remember that the consumer is free to change process for their activities and even override your own activity process.
The calling point would look something like startSdk(context) { state, parent, actions -> /* ... */ }.
This is by far the most comfortable method for the consumer, yet the weaknesses start to show once you leave the area of a typical consumer setup.
2.
Make the Activity open, so sdk users can subclass it.
As you explained this is not possible without making compromies on your end.
Pros: ?
Cons:
The consumer needs to register their subclass and unregister your original SDK activity in AndroidManifest.xml. I'm assuming the manifest merger is enabled. This is a pain, as I often forget to look here.
The consumer gets easy access to your activity and is free to break it as they please.
Unless your documentation is pristine, the consumer will have a hard time figuring out what to override in your activity.
The calling point would look something like startSdk<MySdkActivity>(context).
I really don't understand the benefits of this option, as a consumer. I lose the benefits of #1 and gain nothing in return. As a developer I can't sanction this 'let the consumer deal with it' attitude. They will break things, you'll get bug reports and you will have to handle it eventually.
3.
Here I'll try to expand on the idea mentioned first in comments.
The callback would an abstract class defined by your SDK. It would be used as follows:
The consumer extends this class and defines the callback body. The class needs to have an empty constructor and be static. Typically it would be defined in its own file.
The class name is passed in an intent to your SDK activity.
Your SDK activity reflectively creates an instance of the callback.
The callback class could have several methods, one could set up menu, one could setup only view hierarchy, one would get the whole activity as parameter. The consumer would pick the one they need. Again, this needs to be documented well if there are multiple options.
Pros:
You separate the callback from the call site (where your SDK is called from). This is good, because the callback is executed inside your activity, completely separated from calling code.
As a result you can't leak the calling activity.
The consumer doesn't need to touch AndroidManifest.xml. This is great because registering your callback has nothing to do with Android. The manifest is mainly for things that the system interacts with.
The callback is easily recreated after process death. It has no constructor parameters and it's stateless.
It works across multiple processes. If, by any chance, the consumer needs to communicate across processes they're in charge of how they achieve that. Your SDK is not making it impossible as in case #2.
You get to keep your classes internal.
Cons:
You have to bundle a proguard rule to keep the empty constructor of each class extending the abstract callback class. You also need to keep their class names.
I'm assuming you'll hide the intent passing as an implementation detail so the entry point could look something like startSdk<MyCallback>(context).
I like this one because it shifts all possible responsibilities from the consumer to you, the SDK developer. You make it hard for the consumer to use the API wrong. You shield the consumer from potential errors.
Now back to the first paragraph. As long as the consumer can get their hands on a context (ViewGroup.getContext()) they're able to access the activity and the application (in that process). If both the calling activity and your SDK activity live in the same process the consumer could even access their prepared Dagger component. But they don't get to override your activity methods in unexpected ways.

Is sychronization required when sharing data between Activity and Service?

I've been reading about how to share data between an Activity and a Service. I found some answers here and here. I'm planning on creating a singleton class as this seems like the lowest overhead mechanism to share state.
For my application, I have a service which is acquiring and logging various sensor data and is filling a data structure with the most current state, and then notifying the activity to update the UI with this info, if the activity is visible. If the activity is not visible, then when it becomes visible it consults the state information to update the UI.
I don't see any mention of whether synchronization is necessary. For instance, isn't it possible that the UI thread might be pulling data out of the structure and get interrupted by the service which then puts new data in, resulting in the UI being rendered incorrectly? Also, I want to put a flag on various pieces of data so the front end knows which pieces have been updated: the service would set a boolean and the activity would clear it. It seems like a similar problem could occur here.
Do I need to worry about this, or is it impossible for the UI thread in the activity and the (e.g.) Listener or Receiver thread in the service to interrupt each other. If they can, is it sufficient to use synchronized methods to access the data structure?
For instance, isn't it possible that the UI thread might be pulling data out of the structure and get interrupted by the service which then puts new data in, resulting in the UI being rendered incorrectly?
Possibly. A Service usually has background threads, whether you create them or you get them from specific Service implementations (e.g., the thread used by IntentService for onHandleIntent()). Synchronization is not an issue of components (activities, services, etc.), but rather an issue of threads.
If they can, is it sufficient to use synchronized methods to access the data structure?
Well, personally, I try to use synchronized objects and collections from java.util.concurrent and java.util.concurrent.atomic. Depending on what you're doing and how you're doing it, synchronized methods may be a fine solution.

How to organize Android App code?

First of all: I am rather new to Android App programming and I have a rather basic question:
Already with the sandbox app I am currently working on, the code in the Activity class get quite huge because all the callback methods / listeners (click listener, callbacks from GoogleApiClient) are in there (either by implementing the respective interface or by creating a private class). But I would rather put those into separate classes.
But the question that I ask myself is this: how would I then be able to access the class attributes of the activity class? Sure, I would then probably create setter/getter, but still I first need a reference to the Activity object. How would I get this?
Thanks and regards!
It's a really wide question, since the answer depends by your project and by your programming style. The first suggestion is: move what you can move in one or more fragment. All stuffs related to google play services can be nicely handled in a fragment for example. Listener and callback are UI related components, so they need a Context of an Activity to work, but you can split your UI (again) with Fragment and keep a piece of logic in a Fragment and another piece somewhere else. If you have some logic that runs in background, then you should consider using Service. I tend to have empty Activities, but this is not a rule.

Serialize (or make Parcelable) a Thread in Android

So I have this class that extends the Thread class. I use the thread to connect my phone to a Bluetooth device and keep the connection on.
Once the connection is established (or once the user interacts with the GUI) I need to pass to another Activity.
I'd like to carry with me the thread just created so that I could interact with it (stop it, restart it, modify its status).
Should I make this thread implements Serializable (or Parcelable) and append it as a normal Extra to the Intent calling the other Activity?
Is it possible / correct / convenient ?
If the answer is not, I'd like to know why and which is the most correct method to implement such thing.
Thank you.
Well, Thread is independent from Activity, regardless the fact it's i.e. created there or its inner class (in if your Thread keeps reference to first activity, you are most likely leaking the memory there). If you want your thread fully independent from Activity, you should consider simply separating that functionality. One way is by extending Application and move all the code there. Then no matter what, as long as your application object exists, your thread could be easily reachable thru it. Other option is, as CommonsWare reminded, to just use regular Service and delegate this Bluetooth communication job to it. Whichever you choose, it will be much simpler and better than trying to pass Thread here and there.

Android runOnUiThread - how to pass the Activity

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.

Categories

Resources