Best way to access a parent Activity's data - android

This is a stylistic question more than an actual "how can this be done," but the basic situation is this: I have an Activity MyActivity which contains a MapFragment, as well as a List of Renderers which are my own class that takes care of displaying some data. The Renderers also have ViewPagers which get their content views from yet another class, let's call it ViewPagerTab. Sometimes, something happens in some of these ViewPagerTabs that necessitates the update of the map in the top level Activity. There are, as I see it, a few approaches:
1) Both my Renderers and my ViewPagerTabs contain a reference to the context. If I cast the context as MyActivity I can access its map parameter.
2) By using the reference to the context, I can call getSupportFragmentManager().findFragmentById(R.id.map)).getMap() on it and get the map that way.
3) I can pass the map down from the Activity to the Renderers to the ViewPagerTabs as they are created so the map is accessible in each as a class variable.
4) Use a BroadcastReceiver in my Activity and send a message to it when the map needs updating from my ViewPagerTab.
Have I missed anything? What's the best/cleanest way of doing this?

This lesson may give you some ideas:
Communicating with other Fragments
Basically, the idea is to define an interface in a subunit such as a Fragment, then implement it in the parent Activity. Then, actually call the methods in the interface in the Fragment.

Another alternative is to create a class that extends Application. There, you can "share and declare" a number of non-context specific variables (like a glorified container, but where you don't have to create multiple instances of, or do look ups).
Requires some setup in your manifest but then all your activities can call MyApp app = (MyApp) this.getApplication(); (or in fragments, via the onAttach activity's .getApplication() )

The standard way is to define a listener interface, but I've found this to be cumbersome. Otto is a really nice alternative that you should at least look into before making your decision.

I think this is a bit over my head but what about parcel.I think it wouldn't work because of the dynamic nature of your data however it is one way to communicate between activities.

Related

Define MainActivity as static variable in order to access findViewById method

While I was coding, I wanted to use findViewById method to find a view that cant access in the current view but can be accessed via the MainActivity. So two options came to my mind. One is creating a static method from that object in the MainActivity class and access the static object. The second method is to create a static object form MainActivity class itself(this) and access the findViewById method by calling the static object. Please answer the method I should use.
And apart from that, it got me thinking that whether an Android developer should come across this type of scenario or whether I have done some improper coding to access findViewById method in MainActivity while I was in a different view.
You can take a look at the code in the below repo.
https://github.com/chrish2015/ExpenseTrackerLatest
Thanks
If you are inside a class that is neither a Context nor an Activity and you need to use a method which exists inside the activity or context, then simply pass the activity as a parameter to that class and take an instance to that activity inside your class.
public class MyAdapter extends ArrayAdapter { // this is not activity
private Activity mActivity; // activity is a member of this class.
public MyAdapter(Activity activity, List<String> data) {
mActivity = activity;
}
public View getView(...) {
// if you need to use findViewById:
View view = mActivity.findViewById(R.id.some_id);
}
}
Don't use any of your two methods.
I might be misunderstanding your first sentence, but just to be sure, are you asking for a way to access a View that exists in the MainActivity, while you're inside of a Fragment?
If that's what you're asking, then yes, as an Android Developer, there will definitely be moments where we come across this scenario. However, the solution is definitely NOT by making your Views or Context static.
This is one of the easiest ways to cause bugs to appear throughout your app, with a very high chance to cause memory leaks too. Here's an Article from Google talking about memory leaks related to keeping a reference to a Context: https://android-developers.googleblog.com/2009/01/avoiding-memory-leaks.html
Rather than your two options, there are better solutions that developers typically use.
First of all, keep in mind that you should NOT be directly accessing any Views from outside of your current layout... meaning, that if you're in a second Activity, you don't directly access Views from the first Activity, or if you're in a Fragment, you don't directly access Views that belong to it's FragmentActivity.
Instead, you let the Activity or Fragment handle it's own Views.
So for example, if you're in another Activity and you want to update some data in the previous Activity, you can take advantage of an Activity's startActivityForResult() and onActivityResult() to obtain the data necessary to update the Activity immediately upon returning to the app.
For Fragments, there's actually a tutorial from the Android Documentation that describes a very good way to communicate between other Fragments: https://developer.android.com/training/basics/fragments/communicating
This method is to use interfaces as a callbacks, so another Fragment or the Activity will be able to receive data and update it's Views within it's own layout.
So for your case, if you're using Fragments and an Activity, you can easily have your fragments and activities communicate to each other in a safer and more reliable way.
Also, make sure you read up more on static and it's effects on your code, especially the side effects on Android components. Do not carelessly use static without considering some of the effects it might cause, because that would cause an endless amount of trouble to your code.

Android Best Practice - Communication between Activity and Fragments

Hope you guys can clarify something for me.
I've been using Android for about 6 months now and I'm still confused about the best way to communicate between Activity and Fragments. I've already read the the info on the android developer site.
Fragment to Activity
Right now I know with 100% absolute certainty that an interface is the best way to communicate from Fragment to Activity. I.e. creating an interface in your Fragment and letting your Activity implement it. This way you can call the method from your interface inside your Fragment and have it handled by the Activity (which implements the interface).
Activity to Fragment
Here's were I'm not sure. The android developer site says that in order to communicate with a Fragment you have to put your objects in a Bundle.
Bundle bundle = new Bundle();
bundle.putInt(SOME_IDENTIFIER, myInt);
Now I've been know to use a Singleton class every now and then when I have quite some functionality that I can separate. Say I have a Singleton called PersistenceService where I handle all of the persistence related stuff, e.g. saving something in the SharedPreferences. The PersistenceService will then hold methods like putMyString(String key, String myString) or putSomeObject(String key, SomeObject someObj). This way a class doesn't have to handle persistence itself but can just call the PersistenceService to do it.
Now say I have to update something in my Fragment, a TextView or something.
This is what I do:
String myString = PersistenceService.getInstance(getActivity()).getMyString(someKey);
textView.setText(myString);
I pass in a context (getActivity()) because I need it to get the SharedPreferences.
Now my actual question is:
Do I retrieve my data in the Activity and pass it to the desired Fragment through its Bundle? Or do I simply reference my Singleton right in my Fragment and access the data there directly.
I'm not stuck or anything, but I'd like to know what you guys would recommend.
Any advice, remarks, info etc. is greatly appreciated.
This is a very broad question, and as the pragmatic thinking and learning book says, the answer to most questions in software is "It all depends!".
And it really does, it really all depends, there's no hard rule in software, "always" and "never" are very powerful words that shouldn't be used in software, so, saying always go for "Bundle" info or Never go for a Singleton is a little bit stupid specifically in software, so, instead of telling you exactly what to use, ask your self what would fit better in your needs taking on count things like, scalability, extensibility manageability, etc. For example:
If you go for Bundle, you give some flexibility to your fragment, you are creating some kind of independent component ready to work with whatever information you provide, on the other hand, if you know that you need that fragment only in that place, and the information you will pass is somehow complex(can't be passed using a bundle), why complicating so much? Just go for the Singleton if it does the job simple and clean.
I hope my point is well explained here, there's no hard rules for one way or another, just be as diligent as possible and don't go one way or another just because of laziness or negligence, instead be analyst if it's worth going one way or another based on your needs, and always take on count that not because you went that way this time it will be true for ALL your scenarios.
Hope it Helps!
Regards!
I use bundle when I want send data from fragment to fragment (from fragment to activity by interface, from activity to fragment by bundle).
If data is used in all fragments singleton is the best way, sometime I use also a istance of data objcet in activity that I manipulate in fragment by public methods of activity but I don't think that this is a best pratic.
Please understand that 2 fragments can’t directly communicate with each other, They will need help of the activity under the context of which they are created. Using an interface :).
Implement the interface in a fragment
interface StartCommunication
Define the interface in the activity whose context fragment is using
public class MainActivity extends Activity implements
SendFragment.StartCommunication

What is the difference creating event callback or the activity itself within a fragment?

Lets say I will be using several fragments(Action1Fragment, Action2Fragment etc.) within an activity(ActionActivity). I want to access some elements of activity object, or call some methods of ActionActivity. It is generally offered to create a event callback . What if I keep a reference to ActionActivity within Action1Fragment instead of keeping a reference to CallBackInterface which is actually implemented by ActionActivity since I will be using these fragments only within a particular activity.
I am kinda confused by the idea that Activity might be dead while reference of interface might still be alive(it sounds ridiculous when I read it again but it is OK if I managed to explain myself).
The Android Developer tutorials recommend that you use a callback interface on your fragments. The activity that hosts the fragment must implement the callback interface. The fragment does getActivity() and casts it to the callback interface, and then makes the callback.
This is the recommended way to promote a more modular design. It would not matter if your fragments will only ever work inside one activity. But if you want to make more generic fragments that could be used by different activities, then the above design pattern starts to become useful. (For example: a telephones fragment inside an person fragment and a company fragment.)
Suppose you do it the other way: the fragment does getActivity() and casts it to PersonActivity. The fragment then has access to all the public methods of PersonActivity. But this design pattern becomes much more ugly when you need the other activity to also use the fragment. The fragment would then have to be changed to first try and cast to PersonActivity, and if that throws, try the CompanyActivity.
The recommended design pattern basically gives you a way to make an activity compatible with the fragment instead of vice versa. The fragment only knows about the callback interface and not about any of the activities itself. The activities do know about the fragment because they implement the callback interface but they already knew about it because they constructed and initialized an instance of it.
Does that make sense?

includeed layouts - update in multiple activities

I have an app with multiple activities and multiple layouts. However, one piece of layout is included on several activities. I also have a thread which updates this layout. However, when i switch activity it doesn't work. Since the layout is included the elements have the same ID's, shouldn't it just work? Or do I really need to fetch an object for each element in the layout and feed it into my thread in order to make it update the elements in a new activity?
You should run the update code for each Activity/View, although the XML included is the same, each is a different instance.
My suggestion is on Restart verify is there is any modification to do in each activity, a simple way is to each Activity extend a BaseActivity that has this code.
I include a layout for adverts in my app, but on each activity that uses it, the adverts need to be reloaded.
If I call an activity from one that is using the same included layout when I go back to the previous activity it's still there.
I guess this is what you are seeing....
So you can also save that data inside sharedPreferences (if it is little data and primitive objets or parceable objects).
Also you can extend the Application class and store the data there and update every activity inside the onResume() method. that i believe is the best way to handle this. and this is quite simple to do.
Ask google about extending the application class and he will provide tons of results on how to do it. its an easy way to pass data between activities and/or keep a reference to a single object which you will use throughout the app. Just be carefull to clear it when you wont need it anymore because it will stay in existance untill the application is finished() (which comes with the application extension living thru the whole application lifetime).

Android: launch different activities in a stack, using the same class

I have a similar issue with this one:
Android: Multiple activity instances launched by same intent. Bring one uniquely to foreground?
I need to create a stack of activities, all created by using the same class: it is a class defining a news list, only there needs to be multiple children activities that are also news lists, but from different categories. (I do need to have these activities in a stack)
The trouble is I need to change data on each of these activities after they are shown, but I can't find a way to access each one of these activities separately, since they are all using the same class, so if I used static methods, I would change the data on all these activities at the same time. Ideally, there could be a way to use references of each activity, so that I can access methods on each one separately, but I don't think there is a way of doing this.
I might as well pass parameter IDs when starting each activity, and instantiate objects at the same time, for each activity, and using these IDs later access the respective objects' methods...
Edit to clarify: Let me use an example to what I am trying to achieve. I have an A class and I am using this same class to instantiate multiple activities, in a stack. After the creation of these activities, I need to alter data, say, on one of these activities statically, so by calling A.alterData(); , but not when the activities are created, so there is no way of doing this by starting the activities with different data.. Since there are multiple instances of this class, if I do so, this will result on altering the data on all these activities, that are using the A class. Would I be able to somehow use objects and methods to these objects to alter data on different activities that are using the same class?
any other ideas?
You could use an ActivityGroup. It basically holds a list of activities and you need to control the navigation around them. It sounds like it suits your situation. There are many examples of them that can be found through google.
How I would approach changing the data on the other screens is by using shared preferences. You can store whatever data you need in there, and then (through your activity group) when you change screen, the data is refreshed. This is faster and a little more efficient than restarting the intent every time.
Another way is to change the data in the background without the user noticing. This can be done because an Activity group loads all of the Activity it holds and they are always there in the background, running, unless the developer states otherwise.
You could grab a a hold of the appropriate instance of the class you want to change the data on and then just change it.
Does any of this make sense?
I can elaborate more if needed.
I would supply the parameters to each activity, such as:
intent.putExtra("category", categoryId);
That way you aren't managing too much global state.
About changing the data - if you are talking about refreshing the data from its original source, then you should probably be doing this in the onResume() method of the Activity. Check out the Activity Lifecycle.
This has a few benefits:
you will have access to all of the context of that Activity
you won't have to do something nasty like access another Activity's data
you won't waste time refreshing data the user isn't looking at
Even if you have to make updates to the data, there are ways to make sure each Activity "minds its own business".

Categories

Resources