im trying to send data from fragment 1, to fragment 2.
Im getting a NullPointerException, and i dont quite know why..
I have searched on google and found a lot of articles about, what im trying to do, but i just cant figure out how the general way is done, and if its even possible=(
sorry for using bad english, and im a beginner so...
Code used in Fragment 1
public interface DataMessage {
public void send(String message);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {SM = (DataMessage)activity;
}catch (ClassCastException e){
throw new ClassCastException("Implement message interface");
}
Code Used in Fragment 2
public void getData(String message){
edt.setText(message);
Log.i("Disp", "ListHistoryFragment " + message);
}
Code used in Activity
public class MyActivity extends ActionBarActivity
implements NavigationDrawerFragment.NavigationDrawerCallbacks, ListHistoryFragment.DataMessage
...
#Override
public void send(String message) {
//DisplayFragment DispFrag = (DisplayFragment) getSupportFragmentManager().findFragmentById(R.id.fragmenttest);
DisplayFragment DispFrag = new DisplayFragment();
FragmentTransaction Transfer = getSupportFragmentManager().beginTransaction();
DispFrag.getData(message);
Transfer.replace(R.id.container, DispFrag).addToBackStack(null).commit();
Log.i("Acitivyt", "ListHistoryFragment " + message);
}
Log Cat:
1-22 11:39:01.580 22399-22399/rampanere.packed.package.nl E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at android.rampa.pack.nl.SQL.DisplayFragment.getData(DisplayFragment.java:152)
at android.rampa.pack.nl.MyActivity.send(MyActivity.java:265)
at android.rampa.pack.nl.SQL.ListHistoryFragment$1.onItemClick(ListHistoryFragment.java:73)
EDIT:
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
SM.send(message);
}
To share data between fragments and activities you should keep an instance of the data you are planning to share in your activity. SharedPreferences are intended to other purposes, for example, storing data that you will need whenever your application starts.
Inside your activity declare a protected/public String called message for example.
public class MyActivity extends .... {
public String message;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
}
Inside your first fragment, whenever you want to save your String use.
((NAMEOFYOURACTIVITY) getActivity()).message = "THE STRING YOU WANT TO SHARE";
Inside your second fragment, to retrieve your message use:
((NAMEOFYOURACTiIVTY) getActivity()).message;
For example:
Log.i("The string in","my activity is: "+((NAMEOFYOURACTiIVTY) getActivity()).message);
Related
I have an activity and two fragments. Im trying to get a clicked item from an arraylist. In my fragmentA I have a interface:
public interface GroupListener {
public String onGroupSelected(String groupName);
}
and
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
try {
groupListener = (GroupListener) context;
} catch (ClassCastException e)
{
throw new ClassCastException(context.toString() + " must implement the interface" +
"called GroupListener!");
}
}
This gets the postion from an item clicked in a list :
public void onListItemClick(#NonNull ListView l, #NonNull View v, int position, long id) {
groupListener.onGroupSelected((String) getListAdapter().getItem(position));
}
I then have the listner in my activity and in fragmentB which looks the same:
#Override
public String onGroupSelected(String groupName) {
System.out.println("in onGroup in Activity");
return groupName;
}
#Override
public String onGroupSelected(String groupName) {
System.out.println("in onGroup in fragmentB");
return groupName;
}
But when i click an item only the listener in my activity is activated, not the one in my fragment. What is it that im missing?
The one in FragmentB will not fire, since you are only communicating with the activity from fragment A.
In your activity do something like this:
Override
public String onGroupSelected(String groupName) {
System.out.println("in onGroup in Activity");
FragmentB frag = //find your fragment using fragment manager
frag.onGroupSelected(groupName);
return groupName;
}
This is how you call methods inside fragment from an activity
It is a little late to answer but I found a way that works for me.
As listener will first get by activity, you can define destination fragment in the Main activity and then call a method in the destination fragment and do what you want:
In the main Activity listener
DestinationFragment fragment = (DestinationFragment) getSupportFragmentManager().findFragmentById(R.id.destination_fragment);
fragment.sampleListener(bundle);
In the destination fragment define sampleListener and write your code.
I have a database that provides an array of Strings, accessed from within a Fragment. I want these Strings to go back to the activity attached to the Fragment and set the titles of the tabs in a ViewPager. How can I do this?
This is how I want to do it:
Database String[] → Fragment → Attached activity's ViewPager → New
tabs
Edit: Here is my entire Activity and PagerAdapter code.
Here is my Fragment code
Suppose you have array of Strings and you want to send them to your activity from Fragment, make an interface like
public class MyFragment extends Fragment {
CustomStrings mCallback;
// Container Activity must implement this interface
public interface CustomStrings {
public void onStringRecieved(String[] stringss);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (CustomStrings) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
And then simple use this when you need to send data
mCallback.onStringRecieved(yourStrings); //your data here
And then in your activity implement it
public class MainActivity extends Activity
implements MyFragment.CustomStrings{
...
public void onStringRecieved(String[] stringss) {
// Do something here to use these strings
Toast.makeText(getContext(), ""+strings, Toast.LENGTH_SHORT).show();
}
Hope this solves your problem, for more information refer this
I was trying to communicate between two fragments, but I'm just a beginner so I want to know if there is any solution not using interface....
If there are Fragment A, B, and their Activity:
Sending values from Fragment A to Activity
(In here, Fragment A is a current state)
Sending values from Activity to Fragment B
I know direct communication between two fragments is almost impossible,
but I don't think that makes me to use an interface.
Also, is there any method to use like putExtra() for fragment? I only know using Serializable.
Have a look at the Android deverlopers page: http://developer.android.com/training/basics/fragments/communicating.html#DefineInterface
Basically, you define an interface in your Fragment A, and let your Activity implement that Interface. Now you can call the interface method in your Fragment, and your Activity will receive the event. Now in your activity, you can call your second Fragment to update the textview with the received value
// You Activity implements your interface
public class YourActivity implements FragmentA.TextClicked{
#Override
public void sendText(String text){
// Get Fragment B
FraB frag = (FragB)
getSupportFragmentManager().findFragmentById(R.id.fragment_b);
frag.updateText(text);
}
}
// Fragment A defines an Interface, and calls the method when needed
public class FragA extends Fragment{
TextClicked mCallback;
public interface TextClicked{
public void sendText(String text);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (TextClicked) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement TextClicked");
}
}
public void someMethod(){
mCallback.sendText("YOUR TEXT");
}
#Override
public void onDetach() {
mCallback = null; // => avoid leaking, thanks #Deepscorn
super.onDetach();
}
}
// Fragment B has a public method to do something with the text
public class FragB extends Fragment{
public void updateText(String text){
// Here you have it
}
}
You can communicate between fragments directly by using EventBus - send ordinary or sticky events by one fragment and subscribe to that event in another one.
If don't want message to be lost, use sticky events - it work as sticky Intent in Android. It will be around until it is removed by targer fragment or because another event is pending.
Yes you can transfer data between fragments using bundle like you do in Activity using putExtra
Bundle = bundle = new Bundle();
bundle.putString("key","value");
bundle.putSerializable("serialzedKey",SerializedValue);
FragmentTransaction fts = ((BaseActivity) mContext).getSupportFragmentManager().beginTransaction();
fragment.setArguments(bundle);
fts.add(R.id.fragmentHolder, fragment);
fts.addToBackStack(fragment.getClass().getSimpleName());
fts.commit();
In other fragment you can retrieve data using getArguments()
String key = getArguments().getString("key");
SerializedModel = getArguments().getSerializable("serialzedKey");
you can call a method from the parent activity class that calls a method from fragment B like ((YourActivity)getActivity()).callMethod(T yourData)
Take a look at my Github repo on using interfaces to communicate between fragments.
This is just a really simple example but displays the key concepts.
https://github.com/stoddayy/FragmentInteractionExample
I currently have a fragment containing two spinners and I want to send the information from both spinners to MainActivity. Is this possible? While my code works when I send the information from just one spinner, as soon as I try and send the information from both spinners (per below), none of the information appears to be transmitted:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
onNumberInPartyListener = (onNumberInPartyListener) activity;
onMethodOfSplitListener = (onMethodOfSplitListener) activity;
}
catch (Exception ex){}
}
Do I need to create two onAttach methods, two fragments or is there another way?
Thanks
Update:
So I ended up doing away with the above and instead used an 'Interface' java class to send the information from Fragment 1 to Main Activity, however now I'm having issues sending the information from Main Activity to Fragment 2.
In my Main Activity, I'm sending the information to Fragment 2 with the following code (where 'evenSplit_CalculationFragment2' is Fragment 2 and 'tellMeWhatEachPersonOwesES is the method I've implemented in Fragment 2):
//Send data to Even Split Fragment 2
evenSplit_CalculationFragment2.tellMeWhatEachPersonOwesES(eachPersonOwesESString);
And in Fragment 2 I've implemented this as follows:
//What Each Person Owes (from Main Activity)
public void tellMeWhatEachPersonOwesES (String eachPersonOwesThisESString) {
amountEachPersonOwesES.setText(eachPersonOwesThisESString);
}
However, I'm coming up with a Null Pointer exception for both of these. I've tried testing this by substituting 'eachPersonOwesThisESString' with an actual string (e.g. "test") but most baffling of all I still get a Null Pointer exception. Any help appreciated.
You should use Handler
h = new Handler() {
public void handleMessage(android.os.Message msg) {
// Getting data from Handler
tvInfo.setText("Data from Spinner1: " + msg.what);
if (msg.what == 10)
// do what you need
};
};
You can use one handler with different msg.what codes to distinguish them. Initialise it in activity and send to fragment, it will fire up when you write h.sendMessage
If I wanted to solve this problem, what I'd do is use an event bus (although if you really want, you can technically use LocalBroadcastManager with Parcelables).
With Otto event bus, it'd look like this
public enum SingletonBus {
INSTANCE;
private Bus bus;
private Handler handler = new Handler(Looper.getMainLooper());
private SingletonBus() {
this.bus = new Bus(ThreadEnforcer.ANY);
}
public <T> void postToSameThread(final T event) {
bus.post(event);
}
public <T> void postToMainThread(final T event) {
handler.post(new Runnable() {
#Override
public void run() {
bus.post(event);
}
});
}
public <T> void register(T subscriber) {
bus.register(subscriber);
}
public <T> void unregister(T subscriber) {
bus.unregister(subscriber);
}
}
public class YourFragment extends android.support.v4.Fragment {
public static class SpinnersSelectedEvent {
public String firstSpinnerData;
public String secondSpinnerData;
public SpinnersSelectedEvent(String firstSpinnerData, String secondSpinnerData) {
this.firstSpinnerData = firstSpinnerData;
this.secondSpinnerData = secondSpinnerData;
}
}
#OnClick(R.id.yourfragment_thebutton)
public void theButtonClicked() {
SingletonBus.INSTANCE.postToSameThread(new SpinnersSelectedEvent(firstSpinner.getSelectedItem(), secondSpinner.getSelectedItem()); //pseudo code on the spinner part
}
}
public class MainActivity extends AppCompatActivity {
public void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
//...
SingletonBus.INSTANCE.register(this);
}
public void onDestroy() {
super.onDestroy();
SingletonBus.INSTANCE.unregister(this);
}
#Subscribe
public void onSpinnersSelectedEvent(YourFragment.SpinnersSelectedEvent e) {
String firstData = e.firstSpinnerData;
String secondData = e.secondSpinnerData;
// do things
}
}
So I'm trying to wrap my head around Android Fragments. If I put the following code in my MainActivity:
public void getMessage(Object obj) {
Log.wtf("My object: ", obj.toString());
}
and the following code in my fragment:
((NewNotificationRule)getActivity()).getMessage("Yah wohooo!");
I get the "Yah wohooo!" into my MainActivity. The thing is that this pushes that string from my fragment to my Activity, where I want it to work the other way around. The fragment just defines a couple EditTexts, so upon hitting the submit-button defined in the xml called by the MainActivity, I want the MainActivity to pull the information defined in the EditTexts within the fragment so that it can submit it into the DB. So to conclude: I want to pull something (R.id.myEditText to be precise) from within my MainActivity instead of pushing it from within the fragment.
Is there any way that I can pull the contents of an EditText from a fragment into an Activity? All tips are welcome, since I'm totally lost here..
One fast option (not sure if this is safe or recommended tho) is creating a class in your project with attributes needed to store info and instancing an object of this class in the MainActivity. Then, reference it from the fragment and fill in it the data you need to save (e.g. within an attribute EditText1Data or something) whenever the text is changed or introduced into the fragment's EditText. Then just store into the DB the data contained in the object you filled with the Fragment info. Place some default values to the atttributes in the constructor of this called class to avoid null stuff problems. This can help you easily transfer Data in both directions Activity<-->Fragments , even tho this mightmean you must be very careful since you can get null pointer exceptions.
//This is Your DataClass used to transfer Data between Activity and Fragment.
public class DataClass {
public String EditText1Value;
public String EditText2Value;
public DataManager()
{
EditText1Value="Default Text";
EditText2Value="Default Text";
}
}
//This is the MainActivityClass
public class MainActivity extends Activity{
//instance of the DataClass to be passed to fragments with the method getDataClass
public DataClass dataClass = new DataClass();
//Main Activity code goes here...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
}
//This method returns a reference to the DataClass Object
public DataClass getDataClass()
{
//Return this class instance object of the DataClass class
return (dataClass);
}
//Now this is the method to push data to DB, called whenever an activity button is pressed.
private boolean WriteToDB ()
{
//Suppose this receives a String
WritetoDB(dataClass.EditText1Value);
}
}
//And this is the Fragment that sends data through the DataClass Object
public class ExampleFragment extends Fragment {
//Used to reference MainActivityObject and store info
DataClass dataClass;
//Used to Reference Activity's EditTexts
private EditText editText1;
//TextWatcher used to detect the EditText Field Changes
private TextWatcher EditText1_Txtwtr;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View v = inflater.inflate(R.layout.whatever_layout, container, false);
editText1= (EditText)v.findViewById(R.id.idEditText1);
setHasOptionsMenu(true);
return v;
}
#Override
public void onResume ()
{
super.onResume();
//code...
//Get MainActivity's DataClass object reference.
dataClass= ((MainActivity)getActivity()).getDataClass();
//store info whenever you need to, not necessarily on each keystroke, and store it in the object, not in the DB
dataClass.EditText1Value = editText1.getText().toString();
// Also, to capture whenever a edittext changes, you can use a textwatcher.
EditText1_Txtwtr= new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3)
{}
#Override
public void afterTextChanged(Editable editable)
{}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3)
{
dataClass.EditText1Value = editText1.getText().toString();
}
}
//Asign TextWatcher to your Edit Text.
editText1.addTextChangedListener(EditText1_Txtwtr);
}
}