Since often in Android some functionality is directly implemented in an Activity (e.g. NativeActivity) I am now faced with the situation, that I have 2 Activities that I would like to be "merged" into one because I need both functionality.
So my initial idea would be to write a Proxy Activity, which delegates to internal Activity instances. Is something similar already possible in Android or might this concept even work?
I tried implementing an Activity-Proxy which would delegate to other Activities (which would have to use the same Window, WindowManager, etc.).
Sadly, it does not work since the Activity.attach methods are final/package and they are used for setting up all the internal variables. These variables are then used directly (without a protected or public getter). So with no chance to mend the internals you cannot force all Activities to use the same context and thus you are forced to reimplement the functionality the Activities provide. :(
Use Fragments.
I think this is what you are looking for...
Related
I have an Activity that, with a few modifications, would work extremely well as another part of the app I'm working on. I was wondering if it's possible to easily duplicate an Activity in Android Studio without needing to manually copy all of its dependencies (activity_my.xml for example).
To get it right: You have code you want to reuse in another Activity.
Now, the way I would do this would not be to copy the reused code (because if you want to modify it, you have to modify both copies, which is tedious work).
I'd create a base-activity, that has the functionality that both of your Activities need. This functionality would have to be slightly abstracted so that both activites could use this functionality by extending this BaseActivity and use it for their individual purposes.
If you post some code (the part of code both of your activities should have), I could update my answer to show you how that would look like in your case.
I'm relatively new to Android, and I'm trying to port an app from iOS, which does something slightly unconventional.
My app has an in-house xml language for representing GUI (kind of our own nib/xib in iOS or res/layout/whatever.xml in android, believe me, we had no choice), and an inflation mechanism that inflates this xml and builds a view controller and view instances.
As a result, in iOS, my app had several live UIViewController instances of the same class (added and removed from the navigation stack as necessary) which were all inflated once (from different XMLs) and remained alive as long as the app was.
Now, I'm a bit unsure about the correct way to do this in Android. Ideally, I would like to be able to create instances of an Activity class, each with its views inflated from our xml language, and do the navigation between then. However, to my understanding this is not possible in Android (since activities are started by intents, and created by class).
Is it true that I would not be able to keep activities alive and at the same time - not on stack (i.e. "back" always kills activities)?
If so, does this mean I need to inflate the activities and all their views from xml, every time I navigate "forward" (serious performance issue), or is there an alternative?
Is it reasonable to at least save the parsed xml structure in an Application subclass, so the inflation will be faster?
Would it make sense to only send (on creation) and save (for persistency) an activity identifier to the new activity instance, and have it go to my Application subclass, and inflate itself / get its state by identifier?
In general, assuming having the GUI inflated from XML is a must, and I would like to minimize the need to re-inflate the GUI, what would you suggest as the cleanest solution?
Any other tips will be greatly appreciated… Thanks!
I am not 100% sure I understand your situation - I think what you are saying is that you've got custom XML that defines your layouts and controllers. I am going to answer based on that, correct me if I'm wrong.
First, your questions show an understanding of the problems you face if you go down your current path. I'm not going to answer them individually because I think there's a better solution - use Fragments via the compatibility package.
The way Fragments work is that you have a single Activity, then a series of Fragments inside of it that define the UI. For phones, this ends up looking the same as an Activity-based application. But in your case, it will provide a few bonuses:
Fragments can be created dynamically in code.
Fragments can be popped off the stack, but kept in memory so you can re-add them later.
You can store all of your pre-parsed XML in a retained, invisible Fragment instance (instead of the global Application subclass).
This isn't to say there are no problems with Fragments - there may be limitations there as well (I've only recently started working with them). But I would give them a look to see if they might solve your problem.
Another alternative would be to write a transformation (pre-processed) between your in-house XML and Android's XML. Android's XML View creation is pretty fast because it's optimized for it.
I'm trying to implement a native MapView inside a web-based application framework (quickconnect). Right now the entire framework consists of one Activity (this is unavoidable, as the framework runs the body of the app entirely in a WebView, and the framework parses javascript calls to native functionality, such as sound and native system views). What I've realized is that MapView is an odd beast in that it needs to be run inside of a MapActivity.
So this leaves me with two options, convert the single Activity that runs the framework into a MapActivity, adding methods to manipulate the MapView inside (the issue with this is that we're looking to contribute the code back to the framework project, and the system treats MapActivities differently than normal Activities, causing all non-map apps to use up more resources than necessary), or somehow overlaying the MapActivity on top of the main Activity, which is running the WebView, with the main activity communicating with the MapActivity via Intents.
I fully realize that overlaying Activities is a complete contradiction to the design of Android apps, but I am wondering if it's possible. I've looked into ActivityGroups, and I can't find any examples of a custom ActivityGroup that shows two Activities on the screen at the same time, nevermind overlapping.
tl;dr: Is implementing overlapping Activities possible in Android, and how do I do it?
It is unclear how your objective will actually work. Let's suppose you do have "overlapping Activities". Then what? What have you gained? It's not like the JavaScript code from the first activity can do anything with the second activity. You're going to have to implement 100% of your business logic for the MapActivity in the MapActivity. Since you are going to have to teach "quickconnect" how to call startActivity() regardless, just implement your map as a regular MapActivity, in Java, and be done with it.
If, OTOH, your objective is for quickconnect-supported JavaScript code to manage the MapView, then you have no choice but to refactor the whole of quickconnect to use composition rather than inheritance, so the quickconnect engine can be used inside an Activity or a MapActivity. That may prove necessary over the long haul anyway, since FragmentActivity is necessary for using fragments in the Android Compatibility Library, and one might imagine that quickconnect should provide tablet and TV support using fragments.
Under some circumstances I need to be able to tear down all my activities that are in my application stack and recreate them all due to configuration changes. I have accomplished this by first calling finish for each activity and then recreating the stack.
To recreate, I relauch my root activity. And within its onStart I have it create my second activity. Within my second activities onStart I have it create my third Activity. This does work but the problem that I am having is that when watching the screen you see each of the three activities created and animate into the next activity. I want to have this rebuilding invisible to the user and hide these transitions. Does anyone know how to accomplish this?
Android already takes care of restarting activities when there is a configuration change.
If you are saying you want all of your activities to be restarted, even if they aren't currently visible (Android will do this lazily as the user returns them and they become visible, if the configuration is still different at that point), then no there is no simple way to do this. I can't imagine you coming up with anything that isn't going to be hideously ugly, because to get the platform to restart your activity you will need to make it visible, and then you are going to have flicker up the wazoo.
Things just aren't intended to work that way. This isn't how pretty much any other application you run on Android will operate, so if you deeply feel like it is something you need to do then it will be useful to explain why that is so we can tell you a better way to accomplish what you want. :) For example, if you have a bunch of activities whose state is fundamentally tied together to require this, consider using fragments instead (or cleaning that up).
On the other hand, if you just have some internal concept of a configuration and want to get your activity to be restarted (say for example to switch between themes), there is an API for this but it only was added in Android 3.0: http://developer.android.com/reference/android/app/Activity.html#recreate()
I have developed some apps for Android, and this questions stays always:
How should I structure my UI? Should I launch activity after activity and leave the phone to make the "back" button, or should I choose more optimized, but more complex to implement, way with switching manually Views and then manually doing the "Back" button functionality?
What do you think (or know) is the better practice?
I would say that multiple Activities almost always makes more sense. I just don't think Android is designed for constantly switching its own views - you miss out on so much. You have to implement Back yourself, you don't get any inter-Activity transitions, you have to implement a lot of internal logic to resume an application in the correct state. If you don't partition your app into Activities, it makes it a lot more difficult later on to change the flow of your application. It also results in one mega-Activity that can be a lot harder to handle than a lot of smaller pieces of code.
I have trouble imagining that speed is really an issue; if it is then there's something wrong with the way you're initializing each Activity. For example, I used try to pass Serializable objects between Activities, and that proved to be incredibly slow; when I switched to a faster method of passing objects, the speed of launching Activities increased immensely.
Also, I think it's telling that the Android guidelines for Activity and Task Design don't mention switching Views at all; it's centered around an Activity-as-View design.
I'd like to point out some instances when a single activity might be better design for an Android application that has more than one full screen View:
If the application screens are tightly coupled and share a common Object that they are all operating on. In this case passing around the Object may require a Bundle and can be error prone since there will be copies of it. A good example might be a wizard. Yes you could use static's to access the common Object but static can be dangerous in Android (think configuration changes!)
If you want some really cool animations in between screens. Maybe you want a bird to take off in one screen and land in another screen. Try doing that when each screen is an activity!
On the other hand if one of your screens is designed to be shown by any number of other applications then that screen should be its own Activity.
UPDATE March 2014:
At this point the question should now include the choice of Fragments. I think that Views are probably the least likely choice of the 3: Activity, Fragment, View. If you want to implement screens that make use of the back button then it should be either Activties or Fragments because both handle the back button natively. Fragments will need to be added to the FragmentManager back stack for the back button to work. Managing fragments, dialogs and the back stack can be a bit of an annoyance though!
UPDATE Sept 2018:
Some devs at Google are recommending single activity apps using the new navigation architecture component.
Also keep in mind that implementing your app with multiple Activities will give the user a more coherent experience with the platform as a whole. Part of the experience will be shaped by using the built-in Google apps, so users will probably have an easier time using your application if it behaves similarly to the ones that are already installed on the phone.
Different from others I use a mixture of both, for example,
1. There is a main menu when the application starts
2. You click on search, takes you to search activity
3. Then there's a filter button, which just switches view and shows you filter options
4. There are two buttons at the end of the filter view, You hit "Search" or "Cancel" and you are back to the Search View again (without switching activity)
5. Now if the user hits the phone back button he's taken back to the main menu instead of the search filter options. Which I guess is the correct behavior.
Use it the way user will feel natural. And keeping everything in one activity will make it complex.
It all depends on application, what are you trying to achieve better performance, smoother UI. IMHO I prefer the second approach of controlling the Activities manually even that it is more complex as you have stated. This is a approach I have used in my android tabs project, also you might want to take a look at a class called ActivityGroup (not sure the package) it allows you to have multiple activities that you can switch between, good thing about this class is that your activities are not unloaded when you switch but a bad thing is it takes longer to load your main app.
Just my opinion.
The problem with switching views, that I stumbled upon, is also caused by garbage collector. Seems that GC is triggered when you leave activity and not the view. So, changing tabs with a fairly complex children views, for instance, will almost inevitably lead to stack overflow exception..
I've experienced so many problems with multiple activity layout that I strongly discourage it, unless there's good reason to pick it.
Disadvantage of multiple activities
Using multiple activities it is much hard to refactor code to return data from activity.
If you call a 'sub'-activity then the main activity may be killed. But you never experience that while debugging on a decent device, hence you need to handle always saving state and correctly recovering state. That is a pain. Imagine calling a method on a library (ie. another activity), and you would have to be ensure that when that method returns your app must be able to recreate its state completely with all fields on all objects in the VM (ie. activity.restoreIntance). Its insane.
Also the other way round, when you open a subactivity the VM might have been killed since the subactivity was first spawned, such as when app is minimized while subactivity is displayed.
Its so much cleaner to just have one place to store the relevant app-state, and in my case, most often if VM is killed, I want to return user to main-screen, and let them do their stuff again, because I don't spend 30-50 hours coding save/resume functionality that 0.1% of users will ever experience.
Alternative
Fragments or just manage you activity views yourself. Managing views manually, requires coding some view-switching alternative to activities/fragments with transitions if desired.
And no it does not mean one mega-activity, as suggested in the accepted answer, in any other way than its one mega-app. It just requires a bit more design of the codebase into fitting pieces, because there's slightly more work managing views, though much less work managing activity-state and other weirdness.
Possibly relevant: Reddit: It's official : Google officially recommends single activity app architecture