Pass data between two fragments without using activity - android

I want to pass data between two fragments without using activity and fragment activity.
I don't want to pass data between fragments using activity like this : Communicating with Other Fragments
Below is my scenario :
I have one Parent fragment and inside that there are two child fragments.Now my need is to pass data between these two fragments.How to achieve this?
I looked into this : Event Bus but not getting working example for fragments.
Is there any other alternative to pass data between fragments?
Any help will be appreciated.
Edited as per InnocentKiller's answer :
In FragmentOne , I have implemented :
FragmentTwo = new FragmentTwo();
Bundle bundle = new Bundle();
bundle.putString("Hello", "My name is Siddharth");
fragment.setArguments(bundle);
In FragmentTwo, I have implemented :
Bundle bundle = this.getArguments();
String myInt = bundle.getString("Hello","Test");
mStartTripButton.setText(myInt);

Best Way to exchange data between activity/fragments, fragment/fragment/, activity/activity, class/ class, make a common singleton class like:
public class DataHolderClass {
private static DataHolderClass dataObject = null;
private DataHolderClass() {
// left blank intentionally
}
public static DataHolderClass getInstance() {
if (dataObject == null)
dataObject = new DataHolderClass();
return dataObject;
}
private String distributor_id;;
public String getDistributor_id() {
return distributor_id;
}
public void setDistributor_id(String distributor_id) {
this.distributor_id = distributor_id;
}
}
now set from anywhere(Fragment, activity, class) at any event before you move to new screen
DataHolderClass.getInstance().setDistributor_id("your data");
now get anywhere(Fragment, activity, class)
String _data = DataHolderClass.getInstance().getDistributor_id();

You can use EventBus https://github.com/greenrobot/EventBus to pass any complex object around in Android.
Example passing an object from one Activity to another:
Add your object on the EventBus:
EventBus.getDefault().postSticky(anyObject);
startActivity(new Intent(getActivity(), SomeActivity.class));
Anywhere in SomeActivity:
AnyObject anyObject = EventBus.getDefault().getStickyEvent(AnyObject.class);
This examle is just to show that it works across Activities, you can call getStickyEvent to get anyObject anywhere in your code.
So, you can post an object in Fragment A, and use getStickyEvent in fragment B to retrieve it.
This is especially convenient if you have a lot of arguments and/or complex objects you wish to move from one place to the other. Simply create a single 'holder' object containing getter/setters for the arguments and then pass it along. Much simpler than having to pass them separately and somehow serialize the complex objects.

I think you are trying to pass data from one fragment to another fragment, So try using below code.
Use a Bundle, So write below code in first fragment from where you want to send data.
Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putString("message", "From Activity");
fragment.setArguments(bundle);
and to retrieve that data, use the following code in your other fragment
String strtext=getArguments().getString("message");

Related

Yet another Fragment Communication

There are a lot of questions about fragment communication here, but they are normally question about getting data from activity and sending data back to activity, normally starting from fragment.
But I wonder what what is best approach for sending data from activity to fragment, when you cannot do it when creating fragment? For clarification, Lets assume that an app has 2 fragments that can use (can not must) some data to improve user experience, but obtaining this data is costly. So obtain this data in activity using a Loader or AsyncTask in main activity while creating Fragments themselves. Now when data is ready asynchronously in Activity, we need to send this data to Fragments. What is best approach for this? I thought of a way for doing this, and I like to know if there is any problem with this approach.
1-In fragment we use onAttach to send fragment to activity and check if any data is already read:
#Override
public void onAttach (Activity activity) {
MyActivity act = (MyActivity)activity;
act.addFragment(this);
Data data = act.getData();
if (data != null) {
setAdditionData(data)
}
}
2-and in activity store a WeakReference to Fragment:
private ArrayList<WeakReference<Fragment>> mFragments = new ArrayList<>();
...
public void addFragment(Fragment frag) {
WeakReference<Fragment> f = new WeakReference<Fragment>(frag);
mFragments.add(f);
}
public Data getData() {
return mData;
}
public void updateFragmentsData() {
for (Iterator<WeakReference<Fragment>> iterator = mFragments.iterator(); iterator.hasNext();) {
WeakReference<Fragment> wf = iterator.next();
Fragment f = wf.get();
if (f != null) {
f.setAdditionData(mData);
} else {
iterator.remove();
}
}
}
Now when fragments attaches, it adds itself to list of fragments in activity and checks if data is already ready and if ready it will use that data. On the other hand, when data is ready asynchronously in activity, it can call updateFragmentsData() to update all fragments data.
I wonder if this approach is correct or it can be incorrect in some situations? Any idea? Is there any better approach for notifying fragments from main activity?
Btw, is it possible to use Handler/Message for communicating between fragments too or not? As another approach?
Best Regards
I can think of three ways.
Use a listener. Write an interface in the activity to use it as a listener. The fragment implements the interface and registers and unregister as a listener at appropriate time.(say at onCreateView and onDestroyView).
This one is my favorite. I hope DataBinding is gaining popularity and it can be used to solve this. Say you define a particular model for the fragment layout. Now you use ObservableFields in the model. Pass this model to your databinding variable. Now change this object from either the activity or the fragment itself, changes will be reflected in the view.
The newly introduced ViewModels. I will be using them from my next project.

Sending data from an Adapter to a Fragment in Android. getArguments() returns null

I want to use the data in fragments which is present in the Adapter. I am using setArguments() to send the data from Adapter, and getArguments() to receive the data.
But when I debug it, I am getting a nullpointerException at getArguments.
This is how I am sending the data and receiving it.
In Adapter, to send the data.
ReversalFragment f1 = new ReversalFragment();
Bundle bundle = new Bundle();
String transId = item.getTxId();
bundle.putString("tId", transId);
f1.setArguments(bundle);
fragment class, to get the data.
Bundle arguments = getArguments();
if(arguments!=null) {
String transId = arguments.getString("tId");
if (transId != null ) {
txView.setText(transId);
}
}
Can Anyone help me out how to handle this exception and why is getArguments() null??
Thanks in advance.
use can setTag on a view in adapter and getTag in your Fragment.
there are in built methods you can pass objects in setTag();
#ExportedProperty
public Object getTag() {
throw new RuntimeException("Stub!");
}
public void setTag(Object tag) {
throw new RuntimeException("Stub!");
}
You should call the fragment class object in your Adapter class.Suppose your fragment class name is FragmentB then you should call FragmentB class Object because in your program, it is unable to find out your fragment where do you want to pass the data.
FragmentB f1 = new FragmentB();
Bundle bundle = new Bundle();
String transId = item.getTxId();
bundle.putString("tId", transId);
f1.setArguments(bundle);
You are not specifying the name of the Fragment clearly,
instead of Fragment f1 = new Fragment();
write Your_Fragment_Name f1 = new Your_Fragment_Name();
it will work then.
You should try the other way around. In your current approach you are creating an object for the fragment class in you adapter class and assigning the values to that object, but when you are in your Fragment class it creates a new instance and the values are actually null.
So you must try something like this:
put getArgument() and setArgument() methods in your Adapter class.
I am pretty sure you create the object for Adapter in Fragment class to set it into listview or anything, at that time set and get the values.
For example
in Fragment class:
BaseAdapter adapter = new Adapter(); //constructor called and values set
Bundle args = adapter.getArgument();
now you can have the exact arguments in you need without making any further method calls
Adapter class:
Bundle bundle;
public Adapter(){
bundle = new Bundle();
//put required values
}
public Bundle getArgument(){
return bundle;
}
note that bundle variable is global in Adapter class
Since you would be creating the adapter from your fragment means you have access to your adapter in your fragment.
You can create public String getString() in your adapter and after the adapter is initialized you can call this method in your fragment as adapter.getString()

How can I get access to a fragment method from another activity

I have a fragment which summons a custom CursorAdaper and display it on a ListView
. The thing is I want to change the cursor by changeCursor() from another activity when I add new data, How can I get access to the CursorAdapter displayed on the fragment?
Essentially you have to pass data from one Activity to another and let the fragment of you choice receive the data (each fragment of a given Activity may get the Intent that started/restarted/resumed the Activity).
Consider this code
-- pass data:
String[] myListEntries = getNewListContents();
Intent updateList = new Intent(this, ActivityThatListFragmentBelongsTo.class);
updateList.putExtra("updated_list", myListEntries);
startActivity(updateList);
-- receive data (in fragment):
#Override
public void onResume() {
Intent wasStartedWithData = getActivity().getIntent();
String[] updatedList = wasStartedWithData.getStringArrayExtra("updated_list");
// pass updatedList to adapter
}
Now you might actually have more complicated data than an Array of Strings. In this case
you could create a class that implements 'Parcelable' (http://developer.android.com/reference/android/os/Parcelable.html) and call
putExtra(Parcelable parcel) / getParcelableExtra(String name) on the Intent.

SharedPreferences - Android (different data types)

I have a problem with with sharing data between two different activities. I have data like :
int number
String name
int number_2
int time
int total
I'm trying to make something like order list with this set of data . So it will take one set of data , then back to previous activity , move forward and again add data to it .
I have an idea of making it in array of object - but data inside was cleared after changing activity.
How can I make it ?
I don't know if and how to add Array of object to SharedPreferences , and get value of one element from there.
You should have a look at the documentation of the Intent(s) if you want to do that on the fly associating a key to the value(s) that you want to pass to your second activity.
Anyway, you can think any(sharedpref, database,...) way to pass your parameters but for those kind of things it's a convention and a good practice to follow that.
Don't used share preferences for this...Use the singleton pattern, extend Application, or just make a class with static variables and update them...
You can use .putExtra but since you are communicating with more than one activity the above suggestions are probably the best.
public class ShareData {
private String s;
private int s;
private static ShareData shareData = new ShareData();
private ShareData(){}
public static ShareData getInstance(){ return shareData}
//create getters and setters;
}
Why not to use Intents
Intent intent = new Intent(FirstActivity.this, (destination activity)SecondActivity.class);
intent.putExtra("some_key", value);
intent.putExtra("some_other_key", "a value");
startActivity(intent);
in the second activity
Bundle bundle = getIntent().getExtras();
int value = bundle.getInt("some_key");
String value2 = bundle.getString("some_other_key");
EDIT if you want to read more about adding array to shared preferences check this
Is it possible to add an array or object to SharedPreferences on Android
also this
http://www.sherif.mobi/2012/05/string-arrays-and-object-arrays-in.html

Passing data using Intents

I have two activities, Activity A and Activity B. I pass objects from Activity A to Activity B using intents. When i make changes to the Object in Activity B the data changes does not get reflected in Activity A. Have i missed out on something?
You are missing the fact that when you pass Object O from Activity A to Activity B via intents, activity B receives a COPY of object O. The way things work is that The object O gets serialized (converted to a sequence of bytes) and that sequence of bytes is then passed to Activity B. Then activity B recreates a copy of object O at the moment it was serialized. Any changes to the original object after it was serialized are not reflected in it's copy.
If both activities are part of the same application then just use a static field (or singleton) to communicate between them.
If you are passing a String, then it will not change since they are immutable.
Edit: See below for an alternative to Intent extras.
If you wish to use the architecture of passing immutable objects in messages you can create an immutable serializable data class. Pass an immutable instance of the data class in the intent using startActivityForResult. When the second activity is completed, send a different instance of the same immutable data class back to the first activity where it is trapped in onActivityResult. So in code, given an immutable class PasswordState.java with public final fields.
public final class PasswordState implements Serializable {
Create an instance of this immutable class and send it to the second activity as in:
private void launchManagePassword() {
Intent i= new Intent(this, ManagePassword.class); // no param constructor
PasswordState outState= new PasswordState(lengthKey,
timeExpire,
isValidKey,
timeoutType,
password,
model.getIsHashPassword(),
model.getMinimumPasswordLength()); // NOT minimumHashedPasswordLength
Bundle b= new Bundle();
b.putSerializable("jalcomputing.confusetext.PasswordState", outState);
i.putExtras(b);
startActivityForResult(i,REQUEST_MANAGE_PASSWORD); // used for callback
}
The second activity returns a new object when it is done.
PasswordState outPasswordState= new PasswordState(lengthKey,
timeExpire,
isValidKey,
timeoutType,
password,
isHashPassword,
minimumPasswordLength);
Bundle b= new Bundle();
b.putSerializable("jalcomputing.confusetext.PasswordState", outPasswordState);
getIntent().putExtras(b);
setResult(RESULT_OK,getIntent()); // call home with data on success only
finish(); // go back <=== EXITS Here
Where it is trapped in Activity one.
// ON_ACTIVITY_RESULT used for callback from ManageKeys.java
protected void onActivityResult(int request, int result, Intent data)
{
switch (request){
case REQUEST_MANAGE_PASSWORD:
if (result == RESULT_OK) { // Success. New password.
try {
PasswordState inMessage= (PasswordState)data.getSerializableExtra("jalcomputing.confusetext.PasswordState");
password= inMessage.password;
timeExpire= inMessage.timeExpire;
isValidKey= true;
writeToPrefs(); // support first launch and incoming tagged sms, save pw
}
catch(Exception e){ // data == null, extras == null
password= "";
isValidKey= false;
timeExpire= PasswordState.LONG_YEAR_MILLIS;
Log.d(Utilities.TAG,"FailedToGetResult",e); // will be stripped at runtime
}
...
break;
}
}
When you are done prototyping and the data objects are stable, you can refactor the code to use parcels instead of serializing objects. Since a copy is being sent between activities using serialization, it could be argued that the use of an immutable object is overkill. Using a mutable object and serializing a mutable object to and from the second activity would simplify the implementation.
Hope that helps.
JAL

Categories

Resources