Android : Accessing container activity object from fragment using putExtra? - android

I am building a tab interface using Action bar and fragment. I would need assistance in sending data from container activity to the fragment.
To elaborate, I have job object in container activty. And I have created few tabs based on the information in job object (like company details, experience details etc). I need to pass the job object to these fragments so that it can display respective information.
I have created container activity and tab fragments. I would need an example on how to pass the object across them. I cannot use intent.putExtra. Can I access parent container's object from fragment?
Any help shall be appreciated.
Thanks.

Make the method in your activity, e.g getJob that will return the Job object and its information
MyActivity extends Activity{
Job mJob;
public Job getJob(){
return this.mJob;
}
}
then in your Fragment you do this:
MyFragment extends Fragment{
#Override
public void onActivityCreated(){
super.onActivityCreated();
((MyActivity)this.getActivity()).getJob();
}
}
use getActivity and the method getJob(); to get the object

There are multiple ways of achieving this.
Make a static variable to hold your data and access that data from inside the fragments - this is the most fast but it creates bad design patterns if used improperly.
A way of Fragment-to-Fragment communication possible through the parent Activity is posted here: http://developer.android.com/training/basics/fragments/communicating.html You can use the sample code to just do a Activity - Fragment data send.
The top voted answer here: Accessing instance of the parent activity? mentions a way to avoid using static data (1.) and contains source code examples using ActivityGroup
"If you need access to some values in your First activity without
making a static reference to it, you could consider putting your
activities in an ActivityGroup."
What you choose is your preference, these are just a few options!
Edit: I'm not sure if number 3 will work with fragments since I haven't tested a method similar to it, the example is Activity - Activity communication.

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.

Populating fragment fields from activity

I have a ViewPager of 3 fragments. All 3 fragments are of the same type, with identical layouts, but they are to hold different (text) information. I am trying to create my activity, where I create the fragments and prepare the text data that I will populate my fragments with. However, I can't seem to work with the fragments from within my activity. All the activity's lifecycle methods are executed before the fragment lifecycle methods. So if I try to update a textview in a fragment from within my activity, it won't work, because the textview is null in the fragment.
I'm going to need to make periodic updates to the fragments, so passing the data as a bundle is not an option. Plus, since I'm passing lots of text, I'm using a StringBuilder object, which is not something I can pass in a bundle (unless I make it Parcelable, which I don't want)
I think I could run a method from within my fragment class that would execute during fragment creation, but that means all 3 fragments would run this method. That's not really the level of control I'm looking for.
Is there a neat way to make this work?
Thanks
Keep references to your fragments, and let them all implement an interface with a common update-method. As an example, let's make it super clear and call the interface Updatable with one method called 'update':
public interface Updatable {
public void update(String text);
}
Now, in your Activity's onCreate, save references to your Updatables there (i.e. when you lookup or instantiate your Fragments).
It should now be trivial to update your Fragments when necessary from the Activity. Needless to say, the fragment implementation of the update code needs to do the actual update of the TextView(s).
If the update implementation is exactly the same for all your Fragments, your could save some lines of code and make a base class which implements Updatable and extends Fragment.
you might able to populating fragment fields during onActivityCreated(Bundle savedInstanceState).
Refer to this site for more information about fragments' life cycle:
http://developer.android.com/guide/components/fragments.html
You should consider using Observer pattern... there is a really great implementation which you can include as gradle dependency called EventBus:
https://github.com/greenrobot/EventBus
You can use Otto Bus to send data to your fragments from your activity.
http://square.github.io/otto/
Create a new bus in you application class
Bus bus = new Bus();
Create an event that contains your data which you'll pass to fragments.
bus.post(new MyDataEvent(data));
Register your fragment in your fragment's onResume() (Do not forget to unregister in your fragment's onPause())
bus.register(this);
And get data with subscribe in your fragment
#Subscribe
public void onDataReceived(MyDataEvent event) {
// TODO Do what ever you want
}
I hope this'll help you.

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?

How to pass object between unrelated activates?

I need to pass an object between 2 activities that have no connection between them (meaning, neither of them calls the other).
My Main_activity extends TabActivity. I have 2 tabs : CurrencyList (extends ListActivity implements OnItemSelectedListener) and CurrencyCalculator extends Activity.
I also have class currencyData that saves data about different currencies.
In the CurrencyList activity I created a new currencyData object and initiate it with data.
How can I pass it also to the CurrencyCalculator activity?
2 quick ways:
1. use an static method in your activity to retrieve current ticket id
2. Design and implement an interface and register the fragments as listeners from the activity
Static Method is preferable for large data.
If there is absolutely no connection between them, then one method of accessing data in different Activity classes would be to declare the data members as static class members. Keep in mind that static objects from Activities persist even after you destroy the activity and Android keeps this around for some time even after the you leave the application.
These might not be the easiest ways (just some alternate approaches to the two answers given). You can use a Handler or a BroadcastReceiver to pass the data to the other activity through an intent.
Note
that your object would have to implement either Serializable or
Parcelable if you want to pass it through an intent. I have used
Serializable before and as long as your object does not have any
nested custom objects, you actually have to do no additional work.
Also the assumption is that the receiving activity is alive and is
able to receive the broadcast and/or message.
Another approach would be to write the object to a file (again it would need to be serializable) and read it back in the other activity.

Best way to access a parent Activity's data

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.

Categories

Resources