I am working on a project, which at that stage will have to be customized for different customers. Application consists of some business logic and 15 different activities for the UI. Lets assume that activity A starts B, and B starts activity C. A knows about B, B knows about C. I want to be able to swap activity B (use different layout, a bit different logic to handle user interaction), but leave A and C intact. What is the best approach to achieve that? I will have more and more different activities (serving similar purpose) for different customers, so the solution needs to handle many different configurations.
I was planning on splitting customized activities to different libraries and using DI container (RoboGuice 2.0) to inject them, depending on configuration, but it looks like i still need to put all the activities in manifest.xaml, which requires double work (editing manifest + configuring DI container).
A knows about B, B knows about C.
That does not sound very wise in this case.
I want to be able to swap activity B (use different layout, a bit different logic to handle user interaction), but leave A and C intact.
Then put A, C, and all other common code in an Android library project. Put B and other customer-specific code in a customer-specific project that depends upon the library. Have some means for A (in the library) to determine how best to launch B (for the customer). For example, you could have all customer-specific projects advertise B with the same <intent-filter> (with a nice app-specific and otherwise obscure action string), and A can simply use an Intent that will match that filter for startActivity(). A then knows about B in a generic sense ("here's the B action") without knowing the B implementation, which would be customer-specific.
I was planning on splitting customized activities to different libraries and using DI container (RoboGuice 2.0) to inject them
That sounds like swatting a fly with a Buick, but perhaps you have a long history with DI.
but it looks like i still need to put all the activities in manifest.xaml, which requires double work (editing manifest + configuring DI container)
Drop the DI container, then.
Perhaps, instead of doing anything in your code, you could put your project under version control and, for some of your files, you can then have different branches for different customers.
Related
I'm working on a library project that includes a few activities. These activities would need to redirect back to activities in the host application based on input.
for example:
[host activity#1] -> [library activity] -> [host activity#1]
-> [host activity#2]
-> [host activity#3]
The issue I'm facing is providing a simple api for host applications to define which activity to route to in each scenario. I considered just allowing them to handle it in onActivtyResult, but some scenarios in the library may look like this:
[host activity#1] -> [lib activity#1] -> [lib activity#2] -> [host activity#1]
-> [host activity#2]
Is it normal/correct to create a static class in my library where the host application can define which activities are mean to handle each scenario?
Would it be appropriate to have them extend an interface in some static class that defines what to do in each scenario (the interface forcing them to define what happens in each possible case)?
I'm not quite sure how to phrase this question, and my assumption is that there is better terminology for this problem that would have assisted me in finding what I am looking for by searching.
The issue I'm facing is providing a simple api for host applications to define which activity to route to in each scenario. I considered just allowing them to handle it in onActivtyResult, but some scenarios in the library may look like this...
I don't see any issue with the onActivityResult approach, you can simply chain those calls and still return in to [host activity#1] which will decide where to navigate next.
If you are afraid about writing too much code (which I think you shouldn't), you can consider this workaround: create a base activity class which overrides onActivityResult(). It will have all navigation logic in one place, so all other activities will automatically get it by extending the base activity. Yes, you will have to write a bit ugly code like this:
if (this instanceof Activity1) {
...
} else if (this instanceof Activity2) {
...
}
Indeed, it does look a bit ugly, but it also solves the problem of having the code spread out across multiple activities. Having this code enclosed in one method looks totally fine for me from the maintainability point of view.
Is it normal/correct to create a static class in my library where the host application can define which activities are mean to handle each scenario?
No, I think this is not okay. The library shouldn't know anything about the host application, this is just a poor design. It also will require the host app to set activities to the library before using it, which will make the library less convenient to use.
Would it be appropriate to have them extend an interface in some static class that defines what to do in each scenario (the interface forcing them to define what happens in each possible case)?
Yes, that is perfectly fine and actually is the best way, I think. In this case the library only works through its own interface, it doesn't know anything about the host app. The interface doesn't have to be defined in a class though, I'd prefer defining it in a separate file. This way clients don't necessarily need to see the enclosing class.
I hope this helps. If I didn't answer the question, please provide more details and what you have tried so far.. Thanks, and good luck!
I'm wondering if it is better to have a Module per Activity than a Module per Fragment? In one of my projects, I have an architecture to have a Module per Fragment because I use Activity just to hold and swap Fragments and nothing more. I only create Presenters and Interactors when I need them, i.e. when Fragment.onCreate() is being called.
But I can see guys are creating Module per Activity in their examples. While the idea to have an independent Module for Activity sounds perfectly reasonable as for me from a modularity perspective, but I still believe creating and keeping all objects (Presenters, Interactors) before you actually need them is not a best idea. You can't also release resources when you don't need them, which you could easily do for Module per Fragment when you just release a scoped graph in Fragment.onDestroy() event.
The examples assume you're working with several activities, each with their own clear purpose and scope. There exists a scope A for the application wide dependencies, and scopes B, C and D for each of the Activity dependencies.
You're basically adding an extra layer to the hierarchy: Application-Activity-Fragment. In that case, since you're working with a single Activity, scope A is roughly the scope for the application and activity dependencies, and B, C and D become Fragment scopes.
So yes, it makes sense to create a module for each Fragment.
I have been researching this for about an hour and cannot figure out whether to use fragments within an activity or start a new fragment activity.
Some sites make it sound as if you should have 1 activity and EVERYTHING else is a fragment. Is that the more proper way now? I can't figure out when you use an Activity (or fragment activity) and when you use a fragment.
I have an app for a conference with:
-Speakers (and sub views/activities/fragments) for each speaker.
-Schedule (different sections for each day)
-General info
-Sessions (different sections for each session).
So do I have 4 activities each with their own fragments or do I just use 1 activity with fragments and nested fragments?
You could do it either way, but generally it is best to use an Activity (or FragmentActivity) for each "screen".
If the user sees your app as logically a single screen that has little panels appearing/disappearing for different kinds of data, then use one activity with a lot of fragments. If the user sees it as "going to different screens", then you probably want multiple activities.
If you go with the one-activity-many-fragments model, you may find that your activity's code gets really complicated dealing with all the possible configurations of fragments. That is a good sign that you may want to split it into multiple Activities. Similarly, if you go with the many-activities model, but find that things get complicated as you pass shared data between activities, consider merging the activities.
Converting from Activity to FragmentActivity is as simple as changing the extends and nothing else needs changing.
My conclusions:
I stopped using Activity and only use FragmentActivity as it is more flexible and more up to date and backwards compatible (Using the support library).
If the FragmentActivity has a component that is large enough to be a standalone component, or needs to be one, then I make it as Fragment.
I haven't come across something that would require a complete separate activity to be within another activity, but that should only be used if that component is large enough and completely standalone enough to need an activity for itself.
I don't fully understand your app to be able to make a specific call on which you should use, if you want my opinion, can you provide more details on what you are working on and how are those components connected.
Regards
Another consideration in choosing a more decomposed architecture (many Activities) might be the cost of destruction / creation in the Activity Lifecycle. Do you plan to use Explicit/Implicit intents to leverage existing apps? More death. So, you might have only one activity in a dispatch oriented model and clearly see your apps logic in one place, but how much state will you have to save/restore? Are there performance penalties for re-inflating or populating data resources?
The Android Developer Guide states that activities are launched via Intents:
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
For Fragments, the usual way to display it on the screen is as follows:
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
Why is it that in one case I have to specify a class, and in the other an object? I.e., I would like to use something like
Activity nextActivity = new SignInActivity();
Intent intent = new Intent(this, nextActivity);
startActivity(intent);
Because Activity lifecycle is managed by Android whereas Fragment lifecycle is tied to the Activity in which it is contained.
As mentioned, Activity lifecycle is managed by Android. This is required, among other things, for Android to manage the system resources and also to take care of the back stack.
Fragment, on the other hand, was introduced to modularize and better organize the UI for devices with different sizes. According the the documentation:
Starting with HONEYCOMB, Activity implementations can make use of the
Fragment class to better modularize their code, build more
sophisticated user interfaces for larger screens, and help scale their
application between small and large screens.
To answer the latter part of your question, you can indeed pass the results of an activity to a second activity. But you should never create an instance of an Activity class for that. The right way is to use the startActivityForResult() and send the resulting value to the destination activity through the Intent.
While adding fragment, you are already specifying where exactly to insert that fragment into. So, the ideal way is to,
Create your fragment.
Insert into a layout of your current activity.
Use transactions to remove/manage your fragments, added to the current activity.
In no way, you could launch or use just a fragment, without attaching it to an existing activity.
Android handles Activity life cycle by itself. Just look at the methods of Activity class, they're just like a fill in the blanks. Android calls the shots here. Through these methods it just ask if you want to do something when this activity is created, resumed, paused etc.
The reasons for Android handling activity life cycle internally, are many:
Properly setting up an Activity involves lots of boiler plate code, better let system do it for you. The whole Context and window management is set up for you behind the scenes. Imagine the amount of extra work, if you had to do it for every Activity you created.
Activities are shared, home screen and other applications might want to launch/use them. How would be this possible if they have to call new MyActivity() of some obscure package ? . This is why Activities and other externally invokable components must be declared in application manifest.
Activities from many applications can be parts of an android task ( a piece of work from user's perspective). And are automatically placed/removed/re-arranged on a back-stack. Again, its better Android manage their creation and destruction rather than developers messing with this whole setup.
All user cares is that an Activity must show up when asked for, and just get out of the way if user navigates somewhere else. Android enforces this. Making an Activity appear on its own, or refuse to go away, just because its allowed to be programmed that way, is unacceptable.
Now Fragments , on the other hand are internal. They live inside an Activity and are not accessed from or shared with outside applications or tasks in any way. Fragments are even not a part of application manifest and hence are not exposed outside. Android need not worry about each fragment separately, because fragment life-cycle is bound to that of its parent Activity. Android doesn't care what you do with fragments internally, it can just end the activity and everything inside it is destroyed as well.
I'd like the activity stack for my app to contain multiple instances of the same activity, each working on different data. So I'd have activity A working with data a, b, c and d in my activity stack ad I'd have 4 instances of activity A that I'd call A(a), A(b), A(c) & A(d). I'd also like to arrange it so that if the user asks to work with data c again then it won't start a new activity, but rather will just bring the already running activity A(c) to the front.
Any suggestions on the best way to achieve this?
So I'd have activity A working with
data a, b, c and d in my activity
stack ad I'd have 4 instances of
activity A that I'd call A(a), A(b),
A(c) & A(d).
That will happen by default.
I'd also like to arrange it so that if
the user asks to work with data c
again then it won't start a new
activity, but rather will just bring
the already running activity A(c) to
the front.
I do not believe that is possible unless you create distinct activities for each letter.
I'm not sure you can do it the way you have it described because fiddling with the activity stack like that is not supported AFAIK.
What you could do instead is just use a tab based activity. Each tab could be another instance of activity A working on a different dataset.
I agree with Falmarri (comment), you cant "switch between activities" in the way you are describing. You can however store that data somewhere (file, database, service, global variable, ext.). Where you choose to store that data (a, b, c, d) is up to you and depends on what kinds of functionality you need your data to have.
As for how you "switch" from one to the other, that is somewhat easier than you might think. you dont actually have to "switch" from one activity to the other, you can just swap our all the data. its is perfectly legal (though not always recommended) to have your entire app exist in ONE activity, and merely switch layouts over and over.
My suggestion would be to swap out the data within one activity. you could even specify which data set you want to load initially in your intent filter.