Android start main activity when another activity is called by broadcast - android

I am having an architectural problem with an Android project. I have the main activity(A) where a lot of stuff is initialized then I have 1 Activity(B) that handles some broadcasts from the system, this activity needs to access the stuff initialized by the main activity. If the app is killed and the activity (B) is called the onCreate of the Activity (A) is not called so the stuff is not initialized, how can I handle this situation properly?

That's a sign of not properly encapsulating the logic.
I don't know what your app is about, so that makes it difficult to generalize, but probably your Activity A has a lot of objects and variables related to you model, what you should do is isolate all this logic of your model in a single component, that you can initialize with a single call (or a few lines) either from activity A or B.
This logic can include opening files or sharedPreference, initializing objects, downloading data... Ideally all the logic is isolated from the user interface. The User Interface, on the other hand should be only responsible to present the data in a human readable (and hopefully enjoyable) way.

When first time your activity B is called, pass all initialization values to it from Activity A and save the in Activity B.
If app is killed and activity B is called, it have all the initialized values.

You should develop App using MVC arthitucture
Check this MVC Pattern in Android Development
This will help you batter.

Related

Are there any cons of creating Singleton class with static field to communicate between activities in Android?

There are 3 activities: A->B->C. Each contains a Button (to open next activity) and a EditText.
For example: if I type some text in C and go back to A(by pressing Back Button), how can I see the same text there?
I know 3 solution:
LocalBroadcastManager
SharedPreferences
Create Singleton class with static field and then get this field in onStart method of A - which cons of this solution?
IMHO, there are always cons in using Singleton design pattern in your applications. Some of them are (from the top of my head):
Coupling between otherwise unrelated objects and flows through Singleton's instance
Emergence of a "global state", which makes debug a lot harder
Inability to mock static fields and methods through "conventional" mocking
The fact that a reference to Singleton can be easily obtained in any part of the application leads to a total mess (people stop thinking about dependency graph)
Singletons tend to breed: you introduce one, then another one, then you find yourself with 10 singletons which hold app's state in a "global cloud state"
Note that what you're trying to do is against Android guidelines - if the user taps on "back" button, then he should find the previous Activity or Fragment in the exact same state it had the last time the user saw it, without any additions (unless you explicitly don't want to save it in the back-stack).
If you still want to do it, then I could suggest several options:
Use SharedPreferences and store the value there. Get the value in each Activity and diplay it in onResume()
Use startActivityForResult() call in order to start new Activities and pass the value back in the result. Note that by default press on "back" cancels the action, therefore you'll have to override onBackPressed() method.
Override onBackPressed() method in Activity in such a way that it starts another Activity (instead of just popping the back-stack) and pass the value in the Intent that you use. You might want to use FLAG_ACTIVITY_CLEAR_TOP in this case.
Use some event bus that supports "sticky" events. When user inputs the text you post a sticky event to event bus. In onResume() of Activity you check whether event of this type exists and if it is - you update UI.
Once again - the fact that you CAN do what you want doesn't mean it SHOULD be done.
Simply set into onResume() method of your class A, a call to the Singleton class instance you want to save (or istance of Application class which is the same)
LocalBroadcastManager is not a reliable option. It assumes the bottom activity to still be alive, which might not be the case. While you use B, A might be collected to free resources. Also, you should unregister LocalBroadcastManager receivers onResume(). So, no.
Singletons with static fields are generally to be avoided. It’s not worrying for a single string of text, but singleton fields are easily forgotten and can lead to memory leaks. Better to avoid this pattern if possible, and in your case it is.
Possible options.
If the field is something that must persist, e.g. user editing his username, use SharedPreferences or another storing solution (saving to a server, saving to cache, saving to device SQLite database).
If the field is temporary and is the result of activity B, you can start activity B with startActivityForResult() and then send the result back to activity A through an Intent.
For your problem the simpliest solution - store your value in Application class. Any activity can access it and read/write values.
Cons is that if you accidentally store static reference to activity, it will cause memory leak.
You may try using EventBus for horizontal communication: Activity-> Service, Service -> Fragment, etc.
It has static instance by default plus you can subscribe/unsubscribe to it in onPause and onResume methods.
Another advantage is a STICKY EVENTS - you can post event from Service and it will wait until something handle it - Activity will receive this event when it is ready - after onResume().

Suggested ways to handle object persistence on Android activity recreation

In my Android application there are many instances where multiple activities call a common service passing it a callback
Now if the activity is destroyed and recreated (say due to orientation change) then there is every chance that the callback reference is lost.
I know the normal ways of using onsavedinstance method or an headless fragment of persisting.
But in that Way all my activities have to handle it. Is there any common way to handle this.
Note : I just want to have a simple and reusable code for the persistence to happen
I just want to have a simple and reusable code for the persistence to happen
You can create an activity class where you would write all the state management boilerplate code and then make other activities inherit from this base activity.

Android activity/fragment responsibilities for data loading

When starting a new application for a client, I am asking myself again the same question about who should be responsible for loading data: activities or fragments. I have taken both options for various apps and I was wondering which pattern is best according to you in terms of:
limiting the code complexity.
handling edge cases (like screen rotation, screen going power save, loss of connectivity, etc.)
Option 1 - Activity loads data & fragment only displays it
This allows to have fragments that are just fed a bunch of objects to display. They know nothing about loading data and how we load that.
On the other side, the activity loads data using whichever method is required (for instance initially the latest 50 entries and on a search, loads the search result). It then passes it to the fragment which displays it. Method to load the data could be anything (from service, from DB, ... fragments only know about POJOs)
It's kind of a MVC architecture where the activity is the controller and fragments are the view.
Option 2 - Activity arranges fragments & fragments are responsible to fetch the data
In this pattern, fragments are autonomous pieces of application. They know how to load the data they are displaying and how to show it to the user.
Activities are simply a way to arrange fragments on screen and to coordinate transitions between application activities.
In theory you can do whatever you want, if it works.
Actually, the fragments and activities display data and deal with their own life cycles.
Since fragments belongs to activity so you have to use both in conjunction to better handle all the data but mostly it depends on your needs.
If you keep in mind the idea that the Fragment should provide the UI and the Activity should provide the processing then you have a good division of concerns and code which should allow the Fragment or the Activity to be reused.
If you know about the MVC - Model View Controller - design pattern then you can think of the Fragment as the View and the Activity as the Model.
Things get much more interesting when you build an application with multiple Fragments.
Some key points as a decide factor -
The idea of a Fragment is that it is a wrapped up chunk of UI that
can be used by any Activity that needs it. On this basis you have to
ask yourself if the event that has to be handled is the same for
every Activity or unique to each Activity. If it is the same then the
event handler is better written within the Fragment.
The Fragment doesn't have a UI of its own - it is displayed by an
Activity that the Fragment is associated with. The events are
generated by objects in the View hierarchy, which is owned by the
Activity. If you try to use Android Studio to add an event handler,
for example, it will add it to the Activity and not to the Fragment.
You can define the EventListener that you want to handle the event
in the Fragment and then hook it up to the View object in the
Activity in which you want to generate the event.
A Fragment is a class that implements the onCreateView method to
supply a View hierarchy that can be displayed by an Activity.
To use a Fragment in an Activity you have to add it using a
FragmentManager and a FragmentTransaction. You can add the Fragment
using the add method but nothing happens until you call the commit
method.
After the method that used the commit, usually the Activity's
onCreate, terminates the CreateView event runs the Fragment's
onCreateView and the Fragments View hierarchy is added to the
Activity's content.
You have to write code to save and restore any additional state the
Fragment may have.
If a task is common to all instances of the Fragment then its code
should live in the Fragment.
In particular the code to handle events can be defined within the
Fragment.
The Activity should be used to host code that processes the data
provided by the UI.
Attaching Activity event handlers to the Fragment's UI or is
difficult to do correctly.
From scenarios make decision what your app will be. Is it service,
activity, widget , even a content provider or a complex system,
including some different components. Test your decision against
scenarios.
All of these have to work after the Fragment has been destroyed and
recreated.
(1) Initialization of the Fragment, (2) Saving and restoring the Fragment's
state and (3) Implementing something like an event mechanism so the Fragment
can get the Activity's attention
The hardest part is implementing something like an event mechanism.
In the case of the complex system, distribute functionalities and
data entities among application components. Make a list of components
and what they are (activities or smth else).
Make the list of UI components with description what they do (not HOW
yet) These will be widgets and activities or fragments or layouts
later.
Often you will want one Fragment to communicate with another, for example
to change the content based on a user event. All Fragment-to-Fragment
communication is done through the associated Activity. Two Fragments
should never communicate directly.
When your app is perfectly modular, fragments don't know about each
other. You can add a fragment, remove a fragment, replace a fragment,
and they should all work fine, because they are all independent, and
the activity has full control over the configuration.
You can't do anything with a Fragment unless you start a transaction.
Within the transaction you can set up what you want to happen,
usually add the Fragment to the current layout, but nothing happens
until you use the commit method.
Efficient handling of data with Screen Orientation -
When screen orientation changes, Android restarts the running Activity (onDestroy() is called, followed by onCreate()).
To properly handle a restart, it is important that your activity restores its previous state through the normal Activity lifecycle, in which Android calls onSaveInstanceState() before it destroys your activity so that you can save data about the application state. You can then restore the state during onCreate() or onRestoreInstanceState().
However, you might encounter a situation in which restarting your application and restoring significant amounts of data can be costly and create a poor user experience. In such a situation, you have two other options:
1) Retain an object during a configuration change
Allow your activity to restart when a configuration changes, but carry a stateful Object to the new instance of your activity.
2) Handle the configuration change yourself
Prevent the system from restarting your activity during certain configuration changes, but receive a callback when the configurations do change, so that you can manually update your activity as necessary.
What I would do is manage all data flow (bluetooth, database storage, etc)
in the Activity and use Fragments only for UI display or handling user input.
This way is easier to handle configuration changes/ screen rotations.
Also, if data flow things are heavy to be on UI thread, consider using a Service with a background thread.
If it is a "one shot" thing, you can use an IntentService,
otherwise you can implement a Bind Service and request a bind from anywhere you have Context.
For more read - fragment-and-activity-working-together.
Ideally neither Activity nor Fragment with UI should contain any "model" logic - these classes should be lightweight and responsible only for UI logic. But when you decide to make a separate model object you have a dilemma to choose where to initialise and store this object and how to deal with configuration changes. And here comes some handy trick:
You can create a model Fragment without UI, make it retain instance to deal with configuration changes (it's AFAIK the simplest way to save data across config. changes without troubles) and retrieve it anywhere you need via findFragmentById(). You make all expensive operations inside it once (using background thread, of course), store your data and you're done.
For more info, see Adding a fragment without a UI section.
UPD: There's now a better way to deal with configuration changes: ViewModel from Google's Architecture Components. Here's a good example.
I prefer and always implemented Option-2 over Option-1.
Reasons for not selecting Option-1:
We should have listeners for events triggered in Fragments and pass it back to activity to load data, process it and push it back to fragment, which makes work more complex.
An Activty can load any number of Fragments, Typically you end up questioning these questions to yourself in a scenario where your app is highly scalable and is already huge. Writing all the events in an activity and passing it over to fragment will be an complex altogether.
As #Ved Prakash mentioned, Handling screen orientation becomes complex if orientation is handled by Activty.
I have an example:
your application have 2 features A and B. the 2 features are independent each other. and each feature has a lot of screen.
you should create 2 activities A and B because when Activity A is used, Activity B should be released to reduce memory of app. And the same when B is used, A should be released. The memory of Context A and B are independent, if you want to send data from Activity A to B you must use intent or use global variable in Application Context. intent is managed by OS, not by application. When A send intent to B, if A is destroy is no problem with intent send to B. Activity is App module, it is can call by other applications (fragment is impossible).
for example: feature A has a lot of screen (ex: Fragment1, Fragment2). they use the same data and depend on each other. each screen should be a fragment. and when process with data you can get reference to data by calling function getActivity() and then get reference to variable of Activity context (or Activity memory) to write or read it. Fragment1 and Fragment2 are belong to Activity A Context.it means that Fragment 1 and Fragment 2 can transfer data with each other via variable of Activity context, it is easy to do . noticed that Intent is managed by OS,it is so expensive when send data via Intent.

Android - Getting activity object from startActivity

I need to get the instance of the Activity that was created when startActivity() is called. However, startActivity() returns a void value.
I guess startActivity() doesn't wait until the Activity is created.
Is there a different way for me to get hold of the activity that was just created on the call to startActivity? Or, perhaps I can create an Activity instance myself and register it somewhere so that startActivity can find it.
Is the Activity you're trying to look at in your own app, or in another app?
If they're both your Activities, then it might be OK to do what you're trying to do, although Activities ought to remain separated. You might consider using Fragments instead, since they can "communicate" with each other through their parent Activity.
If they're not both in your app, then you can't get the other Activity instance, because by definition it's in another process. Moreover, the Android system prevents it, because it would be a big security hole.
In general, I squint a bit at attempts to get an instance of something outside of your own component, unless it's an instance of something in the system. Communication between components should be by Intent, bound Service features, or content URIs. Passing around instances leaves you open to memory leaks.

How to make a core of activity on android?

I am new to Android development. After learning from many tutorials I got many Activities and many Fragments. How can I make a core engine to check what Activity is running and what Fragment is showing on a container?
Assume that I have:
Acivity01, Activity02, ... , Activity10
Fragment01, Fragment02, ... , Fragment10
I want to make a class that filters the Activity where Activity is on runtime and what Fragment is embeded to that activity.
How can I do this?
If I understand you correctly, you may want to store some references within your Application class to an Activity and to Fragment instance(-s), which are currently in foreground (by this I mean that user can instantly interact with Activity/Fragment).
As for Activity
Create some Activity field in your Application class and getter/setter methods for it (e.g., setCurrentActivity(), getCurrentActivity()). Then call setCurrentActivity() from onResume() method for each of your Activity instances. Don't forget to call setCurrentActivity, supplying null reference to ir in order to properly handle a case, when there are no foreground activities, but application is stll working.
As for Fragment
The general idea is similar to the first item, but there can be more than one Fragment instance in foreground state at time. So you need to store something like List, where you add your resumed fragments and remove paused.
You may also want to implement something similar for dialogs, for example. Then use the same strategy. Hope it will help.

Categories

Resources