Is it a good way to use a broadcast receiver for syncing multiple data between activities.
My Scenario:
I have DisplayActivity and CreateEditActivity.
On my DisplayActivity I have created a broadcast receiver
that will listen to changes on my CreateEditActivity, also
this activity contain a list of data. Then when I open
CreateEditActivity all the present data in DisplayActivity
will be passed to the CreateEditActivity, on the CreateEditActivity I can create new data item and if the creation is successful I can pass this item thru broadcast. I know that this would be easier using just fragment and listener also using startActivityForResult does not fit on this process for me., But can I implement this process using broadcast receiver to pass sync data between activities. Hoping for suggestions.
I don't think it's a good idea.
Only one Activity is at the top of the stack at a given time. You should not make the assumption that your other Activity is alive. The system could have killed it. (You can test this by enabling the developer's option "Don't keep activities".)
It would be better to use persistent storage (Room, SharedPreferences or so). You could also try ViewModels(https://developer.android.com/topic/libraries/architecture/viewmodel) to avoid the burden of handling lifecycle events.
If you don't want persistence and your data can implement Parcelable just pass them to the other activity through Bundle.
Related
I have my MainActivity which gives the user a selection of pages to open, all of which involve downloading some data from the internet and displaying it. To save the user waiting when they choose their page I've made an AsyncTask as a subclass of MainActivity which produces an object DATAwhen the download is complete.
How would I pass DATA on to the SecondActivity in the following circumstances:
The user chooses the SecondActivity before the AsyncTask download has completed.
The download completes before the user chooses the SecondActivity.
the AsyncTask doesn't have to be a sub-class of MainActivity its just been tidy to do it that way so far,
thanks for the help!
Here's one way to do this:
Create a reference to your data in your Application. The Android Application is a good place to store global data. Next, populate the data via your AsyncTask (Watch out for the pitfalls of using an AsyncTask). You can now access your data via a call similar to this: ((MyApplication)getApplication).mydata
As you mentioned, two scenarios can come up. Either the data has been populated, or not. To handle this, use an observer that observes changes to the data. Have SecondActivity register as an observer when the data is null. When the data is available your SecondActivity's update method will get called and you can do whatever you please with it. Finally, make sure to unregister from being an observer.
Hope this helps.
Passing information directly between activities works only if it is Parcellable (via Intent). Almost anything could be made Parcellable but it is not always a good idea especially when the amount of data is large.
The next problem is that your AsyncTask most likely keeps the Context of your first activity alive when it is running longer than the activity lasts. Activity instances are quite often recreated when you rotate the device and naive implementations tend to start another asynctask in the new instance and end up with multiple tasks that download the same data. You would need to pass the reference of a running task between instances of the same Activity.
The simplest solution is probably to create a singleton (or a Service) accessible from both activities that hosts the AsyncTask & loads the data. If it requires a Context use getApplicationContext() since that's safe to use outside the lifetime of Activites.
Activities could register themselves as listeners for "data loaded" events while they are active.
I've recently struggled with AsyncTask and had difficulty having the UI behave while the task was running in the background. While there are comments around that services aren't really appropriate for the sort of thing you're describing, I've found them much easier to work with. You might check intentService as a middle ground. Good tut's can be found here and, specifically concerning intentService, here.
My fragment represents dynamic information which is obtained asynchronously. I am interested in how to provide the DAO/DTO to the fragment. Should the fragment maintain a reference to the DTO? What about updates. Should it request updated DTO and be the listener on these async calls or request that the activity make the requests and then update the fragment when the async response arrives?
There isn't really a "best practice" way to do this in Android. There are many ways and many of them are valid.
My recommendation would be to create a service that keeps track of changes in the data and report back to the fragment that requires it. Should be careful with this and make sure the service is only active when required, otherwise we can get background tasks that drain the battery.
The simplest way to register a BroadcastReceiver when the fragment is visible (after onResume, remove in onPause). This is like the intent filters that you can set for activities in the manifest. Here is a nice example: http://www.vogella.com/articles/AndroidBroadcastReceiver/article.htmlz
Once the receiver gets the intent there are 3 possible ways to procede.
Create a DAO and access the data (possibly a bit slow)
Use a ContentProvider and receive the new items in the intent sent to the receiver
If your data is Serializable or Parcelable you can add the new new data to the sent intent. (Possibly the fastest)
UPDATE
There is a useful tool for this kind of task that I forgot to mention: Loaders
They provide a simple way to handle data sources (like content providers).
I am developing an application which has around 8 Activities, and a class which is used to connect/receive data to/from an embedded Bluetooth chip. When I started, a Bluetooth object was initialized in my initial Activity, where there was a Handler which received messages from the Bluetooth object.
After poking around on the internet for a while, it seems like the best idea for me is to turn my class into an Application subclass. However, doing this removes the need for me to initialize an object in the MainMenu, which removes my ability to pass it the Handler used.
Does anyone know of a way to eliminate the need for a Handler, so that every time the Bluetooth Application changes it state or receives data, the current Activity can access it?
My main problem with this approach is that the Activity doesn't know when the Bluetooth Application will be sending it messages, the Application waits and listens, and then notifies the Activity when it happens.
OR
Is it bad practice for me to write the Handler into the MainMenu, have it handle messages for ALL the different activities, and then pass the Handler from Activity to Activity?
I'm going to assume that you're trying to achieve the following as it's a little unclear from your question your ultimate aim (sorry!):
Your application has several activities but only one Activity receives the data from the bluetooth device.
The other activities in in your application require the data from the bluetooth device but are not receiving it directly from the bluetooth device. Currently you're providing the data via the one activity mentioned above.
You want to NOT use a Handler to achieve this.
If my above assumptions are correct then you are going along the correct lines but you probably do not want to use a Handler.
You are quite correct in having one Activity handle all the interactions with the Bluetooth device. It simplifies things and provides a much better, cleaner way of handling the Bluetooth device. However you need to get the data from this one Activity to all the others and to achieve this you would probably want to use Broadcasts, BroadcastReceivers and Intents. See here for an overview.
However if you can you might want to take a look at using LocalBroadcastManager as this keeps any broadcasts within your own app's space. Broadcasts are global and should be avoided if you do not need to pass the data outside of your own app due to security implications.
Finally, have you considered using Fragments for your other Activities? Another disadvantage with Broadcasts is there is extra overhead associated with them. If you're keeping data within your app then you can create an interface to be implemented by each of your Fragments and your main activity just calls that interface on the Fragment that is currently selected.
You can use BroadcastReceiver class to send broadcast messages to your activities. see here http://developer.android.com/reference/android/content/BroadcastReceiver.html
When you get the data you need into the application class, you can send it to the activity you want.. just make sure that the activity has registered to receive that broadcast message..
I've got a little gap in my knowledge here and I want to make sure I do it right before writing all the wrong code.
I have an Android app that extends Application to set up some core functions for a TCP client. There are a few different Activity screens that should interact with Application. What I'm stuck on, is what to do when a data packet is received by Application. I want to relay it to the currently-visible Activity, whatever it is.
Coming from a C# background, I'd just create an Event in the Application, and simply subscribe to that event when an Activity is created. But I'm getting confused with Java Listeners, Handlers, ...
What's the best way to go about that? Should I be doing a Service instead? (But I don't really care if the TCP connection is killed when the app is not shown.)
I would go with a LocalBroadcastManager (documentation) approach.
Create one of those puppies in your Application class, and register/unregister your Activity objects in onStart and onStop. See Context.registerReceiver. Note that this requires using Intents, which might be too restrictive/heavy-weight for your application; packing/unpacking data can be a chore.
Alternatively, you don't have to use any specific android class to do it--just keep track of what Activity your program is in by calls to your Application in onStart and onStop. Might help clean your code if you make all of your activities-of-interest extend a subclass of Activity that contains this logic.
I want to pass a parameter between two activities at a certain time interval. The passed parameter is an int, that represents the number of satellites seen by the device and is used to draw a chart in the second activity.
There is no harm in keeping a GpsStatus Listener in both of those activities provided that you stop GPS properly when not needed. :)
But anyway, If I were you I'd let the Application class hold on to these details. I'd use a Service to listen to the GpsStatus and the Application class bind to this service. Your Application class is now the gateway. Your activities can now smoothly communicate with the Application data, instead of the clumsy Intents.
This pattern is taken from here
It is very likely that you are trying to do something in a strange way because you do not fully understood yet how activities in Android are working.
There is only one active Activity in your whole app. Sending data from one activity to another is only needed if the users changes the active Activity, either through clicking on a button and switching to a new Activity or through clicking back and going back to the previous Activity. Please read the Activity Lifecycle very carefully to understand how activities should be used.
I assume that you have registered a location listener in one activity and try to use the values of this listener in other activities. Normally you would use the onPause method to deactivate the listener in the first activity and then activate a new one in the new activity. This will get you the number of known satellites in every activity. If the user goes back you will have to reregister the listener in the onResume method to reenable the gps updates for the new Activity.
Keeping an active GPS Listener in a paused Activity will lead to an active GPS Sensor even if your App is in the background and not used anymore. This will drain the battery of the phone very fast and very likely have your app uninstalled in an instance.
You could use a shared preference to store the int in a kind of variable that both activities can access.
Otherwise, try a custom intent and implement a receiver in one or both Activities. This is a little harder to implement, but with the receiver you can act as soon as the value changes.
If it is rather important to do it in the time interval, use a shared preference ;-)
You can also pass bundles between two activities. That Intent can be used for storing
parameter values in PutIntent.
More information here: http://remwebdevelopment.com/dev/a33/Passing-Bundles-Around-Activities.html