android calling a MainActivity function from a fragment - java

I'm new to android and I'm trying to get a hang of creating and using Fragments.
I have a fragment that shows a simple list of multiple dates to choose from and implements an onClickListener. The idea is once a user chooses a date, the fragments sends the date back to the MainActivity which then runs a query in database and sends the database response to another fragment.
I'm stuck on the point of sending the date back to MainActivity, elegantly. I can't find much info. I found this:
Activity activity = getActivity();
if(activity instanceof MyActivity){
MyActivity myactivity = (MyActivity) activity;
myactivity.myMethod();
}
I'm very new to this but this seems hacky to me. Is this the right way or is there another way?
Any input is appreciated

I prefer the interface based approach because is very clean. You can declare a nested interface in your Fragment or an external one:
interface OnMyStuffListener {
void myMethod();
}
Make the Activity to implement that interface:
public class MainActivity extends Activity implements OnMyStuffListener {
#Override
public void myMethod() {
// Do whatever you want.
}
}
The Fragment will be attached to the Activity so you can check the instance of the Context and cast it to the Activity:
public class MyFragment extends Fragment implements View.OnClickListener {
private OnMyStuffListener mListener;
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnMyStuffListener) {
mListener = (OnMyStuffListener) context;
} else {
throw new IllegalArgumentException("The context " + context.getClass().getName() +
"must implement " + OnMyStuffListener.class.getName());
}
}
#Override
public void onDetach() {
super.onDetach();
// Release it avoiding memory leak.
mListener = null;
}
#Override
public void onClick(View v) {
mListener.myMethod();
}
}

YES this is absolutely right. You can use this, if you are not sure that your Fragment is attached to Activity
You can also achieve this by using Interface, using an EventBus like LocalBroadcastManager, or starting a new Activity with an Intent and some form of flag passed into its extras Bundle or something else.
Here is an example about using Interface:
1. Add function sendDataToActivity() into the interface (EventListener).
//EventListener.java
public interface EventListener {
public void sendDataToActivity(String data);
}
2. Implement this functions in your MainActivity.
// MainActivity.java
public class MainActivity extends AppCompatActivity implements EventListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void sendDataToActivity(String data) {
Log.i("MainActivity", "sendDataToActivity: " + data);
}
}
3. Create the listener in MyFragment and attach it to the Activity.
4. Finally, call function using listener.sendDataToActivity("Hello World!").
// MyFragment.java
public class MyFragment extends Fragment {
private EventListener listener;
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
if(activity instanceof EventListener) {
listener = (EventListener)activity;
} else {
// Throw an error!
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my, container, false);
// Send data
listener.sendDataToActivity("Hello World!");
return view;
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
}
Hope this will help~

Related

Android/Java: How to execute in background, functions of activity B from activity A without showing the activity B?

I have two classes corresponding to two activities in my code.
What I would like, is that the functions in the class of the activity B is launched in the activity A, but without showing the activity : I would just like the code to be executed...
How can I launch the functions of the activity B in background from the activity A?
I read to use Services, but I don't know at all how to use them, I don't see so many reading about it. I don't know if it is the good way.
I tried this with no success: startService(new Intent(this, HereMap.class));
Activity A:
public class LoginActivity extends AppCompatActivity {
#Override
protected void onResume(){
...
//Code to execute the activity B in background
Intent activityB= new Intent(this, HereMap.class);
activityB.onDownloadButtonClicked(); //=> here is the execution but doesn't work...
}
#Override
protected void onCreate(Bundle savedInstanceState) {
...
}
Activity B:
public class HereMap extends AppCompatActivity {
...
private MapLoader.Listener mapLoaderHandler = new MapLoader.Listener() {
#Override
public void onProgress(int progress) {
Log.i(TAG, "Progress " + progress + "%");
downloadProgressBar.setProgress(progress);
}
#Override
public void onInstallationSize(long diskSize, long networkSize) {
Log.i(TAG, "Map data require " + diskSize);
}
#Override
public void onGetMapPackagesComplete(MapPackage rootMapPackage,
MapLoader.ResultCode resultCode) {
if (resultCode == MapLoader.ResultCode.OPERATION_SUCCESSFUL) {
Log.i(TAG, "Map packages received successful: " + rootMapPackage.getTitle());
currentInstalledMaps = new ArrayList<>(1);
populateInstalledMaps(rootMapPackage);
} else {
Log.e(TAG, "Can't retrieve map packages: " + resultCode.name());
Toast.makeText(HereMap.this,
"Error: " + resultCode.name(), Toast.LENGTH_SHORT).show();
return;
}
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Init map
setContentView(R.layout.activity_here_map);
mapFragment = (AndroidXMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapfragment);
...
public void onDownloadButtonClicked() {
Log.d(TAG, "Downloading new map data...");
List<Integer> downloadList = new ArrayList<>(1);
downloadList.add(120214); //Id:120002 Berlin Id:120214, Name: Andalucia, Size:231504 Cherche l'id avec l'application iOS map-downloader-ios-swift
downloadProgressBar.setProgress(0);
downloadProgressBar.setVisibility(View.VISIBLE);
MapLoader.getInstance().installMapPackages(downloadList);
}
If you have some function you want to use in multiple Activities, you can put it in its own class and instantiate that class in whatever place you need to call its methods. The created class should not extend Activity or Fragment if it isn't actually an Activity or Fragment (this will cause all sorts of bugs). If it needs access to a Context or other Android component, you could pass those in at construction or to the methods that need it.
If you need your helper class to interact with its hosting activity (e.g. show or hide views, send data to views, etc) you can define interfaces on the helper or pass the views in directly.
If you define interfaces on your helper class you can use those to "call back" to whatever activity is hosting it (e.g. to show a progress bar). If you don't want to use an interface you could just pass the view to the helper class too, but the interface approach is sometimes more flexible.
Here are examples of both approaches:
Using an Interface
public class MapHelper {
public interface ProgressBarHolder {
void showBar();
}
private ProgressBarHolder progress;
MapHelper(ProgressBarHolder prog) {
progress = prog;
}
public void onDownloadButtonClicked() {
List<Integer> downloadList = new ArrayList<>(1);
downloadList.add(120214);
progress.showBar();
MapLoader.getInstance().installMapPackages(downloadList);
}
}
then you can call it from any Activity, like this
public class MyActivity extends AppCompatActivity
implements MapHelper.ProgressBarHolder
{
private MapHelper helper = new MapHelper(this);
private ProgressBar bar;
#Override
public void showBar() {
// show a progress bar, MapHelper will call this
// when it needs the current activity to show a progress bar
bar.setProgress(0);
bar.setVisibility(View.VISIBLE);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set up stuff
bar = findViewById(R.id.progress);
bar.setVisibility(View.GONE);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
helper.onDownloadButtonClicked();
}
});
}
}
Passing in Views
public class MapHelper {
private ProgressBar progress;
MapHelper(ProgressBar prog) {
progress = prog;
}
public void onDownloadButtonClicked() {
List<Integer> downloadList = new ArrayList<>(1);
downloadList.add(120214);
progress.setProgress(0);
progress.setVisibility(View.VISIBLE);
MapLoader.getInstance().installMapPackages(downloadList);
}
}
then you can call it from any Activity, like this
public class MyActivity extends AppCompatActivity {
private MapHelper helper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set up stuff
ProgressBar bar = findViewByid(R.id.progress);
bar.setVisibility(View.GONE);
// Wait to create the helper until you have the views
helper = new MapHelper(bar);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
helper.onDownloadButtonClicked();
}
});
}
}

How to make a method communicate with both an Activity and a Fragment?

I have an app consisting of (among other things) one Activity and one Fragment. In the Activity som data is displayed using TextViews, and in the Fragment the user can input some data using EditText-views. I have a method which takes data from both the Activity and Fragment, performs some calculations and finally displays a result in both the Fragment and the Activity. This method currently works when I call if after editing the text in any of the EditText-views in the Fragment. However, I also want to call it each time I update the data in the Activity but when I attempt this, I can not fetch the EditText data because they return null.
So my question is: what is good practice, or the ”right way” to do when dealing with methods that are supposed to be reached from both an Activity and a Fragment? I would greatly appreciate if someone could lead me onto the right track.
I have read the official documentation on Fragments and there ViewModel was mentioned. But this doesn’t seem suitable in for my application since I want the Activity to be involved. Do I need to use this or can I go through my main Activity? I’ve also read about Interfaces, but I’m not sure which one would suit my project best. I’m currently using Interfaces, but I’m not sure if I’m doing it correctly.
I’ve also watched this video and read these following questions:
Shared ViewModel to help communication between fragments and parent activity
Call a fragmentMethod from another fragment, but can't refer to them in parentFragmentActivity's View pager
how to manage the fragments in android correctly?
"My God"’s reply to this question was helpful but I’m still not sure what is the best thing to do in my case, as I have a Fragment where user can input data, and the same fragment should also view data as a result of that input. (Maybe my first mistake is building the app like this?)
I provide some code in case it is helpful.
public class AccuracyFragment extends Fragment {
EditText editTextLevel, editTextAccuracy;
private OnFragmentInteractionListener mListener;
public AccuracyFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_accuracy, container, false);
editTextAccuracy = view.findViewById(R.id.text_accuracy_character);
editTextLevel = view.findViewById(R.id.text_level_character);
TextWatcher watcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
//Doing nothing
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
//Doing nothing
}
#Override
public void afterTextChanged(Editable editable) {
updateFragment(Float.valueOf(editTextLevel.getText().toString()), Float.valueOf(editTextAccuracy.getText().toString()));
}
};
editTextLevel.addTextChangedListener(watcher);
editTextAccuracy.addTextChangedListener(watcher);
return view;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null; //I don’t know what this does
}
#Override
public void onResume() {
super.onResume();
// updateFragment(); //Should I have this?
}
public interface OnFragmentInteractionListener {
String[] onAccuracyFragmentInputChanged(float levelFromFragment, float accuracyFromFragment); }
public void updateFragment(float level, float accuracy) {
//Complicated method doing things with editTextLevel and editTextAccuracy. However, it doesn’t work when this method is called from outside AccuracyFragment – EditTexts are null
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onDestroyView() {
super.onDestroyView();
}
#Override
public void onStop() {
super.onStop();
}
}
 
public class MainActivity extends AppCompatActivity implements AccuracyFragment.OnFragmentInteractionListener, AdapterView.OnItemSelectedListener {
AccuracyFragment accuracyFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_new);
selectedID = null;
textView1 = (TextView) findViewById(R.id.text_1);
textView2 = (TextView) findViewById(R.id.text_2);
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.fragment_container) != null) {
// However, if we're being restored from a previous state, then we don't need to do anything and should return or else we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create a new Fragment to be placed in the activity layout
accuracyFragment = new AccuracyFragment();
}
}
//This is the core method which takes the value from two EditTexts in the Fragment, and two TextViews in the MainActivity
private String[] getRequiredAccuracy(float firstValueFromActivity, float secondValueFromActivity, float firstValueFromFragment, float secondValueFromFragment) {
//This methods uses parameters from the Activity, and two from the Fragment, and is intended to be called from both the Activity and from the Fragment itself
String returnValues[] = {s, q, r, c}; //This method is too complex to show, but it will end up outputting some values
return returnValues;
}
public void methodCalledUponClick(View view) {
//After showing a Dialog with some choices, I intend to call the method from fragment:
accuracyFragment.updateFragment();
}
#Override
public String[] onAccuracyFragmentInputChanged(float levelFromFragment, float accuracyFromFragment) {
String returnValues[] = {"0", "0", "0"};
if (selectedID != null) {
if (textView1.length() == 0 || textView2.length() == 0) {
//Do nothing if any of these are empty
} else {
returnValues = getRequiredAccuracy(Float.valueOf(textView1.getText().toString()), Float.valueOf(textView2.getText().toString()), levelFromFragment, accuracyFromFragment);
}
}
return returnValues;
}
}
}
You can go ahead with callback/Interface to communicate with fragment and activity simultaneously.
For Creating callback/Interface:
public interface CallBackListener {
void onCallBack(String value);// pass any parameter in your onCallBack which you want to return
}
In Fragment Class:
public class AccuracyFragment extends Fragment {
private CallBackListener callBackListener;
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//getActivity() is fully created in onActivityCreated and instanceOf differentiate it between different Activities
if (getActivity() instanceof CallBackListener)
callBackListener = (CallBackListener) getActivity();
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
EditText editText = (EditText) view.findViewById(R.id.edittext);
editText.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if(callBackListener != null)
callBackListener.onCallBack(s.toString());
}
});
}
}
In your Activity:
public class MainActivity extends AppCompatActivity implements CallBackListener
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onCallBack(String value) {
Toast.makeText(mContext,"onCallback Called",Toast.LENGTH_LONG).show();
}
}

Launching Fragment B from Activity based on data collected from Fragment A with less boilerplate code

I have the following setup:
I have an Activity that launches a FragmentA.
FragmentA contains a recyclerView and an adapter.
I have an interfaceA in the adapter which is implemented in FragmentA so that I get notified which position was clicked.
I have a second interfaceB that I created in the FragmentA, which is implemented in the Activity that launched FragmentA in step 1.
Finally, I'm launching FragmentB from the Activity based on data I get from interfaceB.
Everything is working fine, however the flow is tedious, and demands a lot of boilerplate code.
THE GOAL is to have the activity launch fragmentB that contains data from a single clicked item from the recyclerView within FragmentA.
Question: Can it be achieved differently?
Code Below:
Activity launches FragmentA:
Fragment fragment = fragmentManager.findFragmentByTag(FragmentA.class.getName());
if (fragment == null) {
fragment = Fragment.instantiate(this, FragmentA.class.getName());
}
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction
.replace(R.id.fragmentLayout, fragment, FragmentA.class.getName())
.addToBackStack(FragmentA.class.getName())
.commit();
Inside FragmentA we have recyclerView, and interfaceA implemented in the adapter:
Adapter Class:
public class AdapterA extends RecyclerView.Adapter< AdapterA.ViewHolderA> {
//instances
private Context context;
private List<Data> dataList;
private OnItemClickListener onItemListClickListener;
//Constructor
public AdapterA (Context context, List<Data> dataList, OnItemClickListener onItemListClickListener {
this.context = context;
this.dataList = dataList;
this.onItemListClickListener = onItemListClickListener;
}
onCreateViewHolder....
onBindViewHolder....
getItemCount...
class ViewHolderA RecyclerView.ViewHolder {
//instances..
//Constructor...
}
}
interface class interfaceA:
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
interface class interfaceB:
public interface SingleItemEventListener {
void onSingleItemClicked(int position);
}
FragmentA class:
//Instances
private AdapterA adapter;
private RecyclerView recyclerView;
private onSingleItemClicked singleItemEventListener;
onAttach...
onCreateView...
#Override
public void onStart() {
super.onStart();
//Setting adapter
onSetAdapter();
}
private void onSetAdapter() {
List<Data> dataList;
dataList = getData();
adapter = new AdapterA(context, dataList, new OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
singleItemEventListener.onSingleItemClicked(position);
}
});
In the Activity, we are implementing onSingleItemClicked callback to receive the event and launch FragmentB with data received from the interface callback:
ActivityA implements SingleItemEventListener {
#Override
public void onSingleItemClicked(int position) {
Data data = getData(position);
if (data != null) {
Bundle bundle = new Bundle();
bundle.putParcelable("single_data_key", data);
Fragment fragmentB = fragmentManager.findFragmentByTag(FragmentB.class.getName());
if (fragmentB == null && bundle != null) {
fragmentB = Fragment.instantiate(this, FragmentB.class.getName(), bundle);
}
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction
.replace(R.id.FragmentLayout, fragmentB, FragmentB.class.getName())
.addToBackStack(FragmentB.class.getName())
.commit();
}
}
}
Add ViewModel to your activity and use it to communicate between all you components, activity and both fragments.
You can get access to the activity's ViewModel from your fragment
MyViewModel model = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
Use LiveData for communication, post an action to it from your fragment and listen to it in your activity to start another fragment.
You can do the same task using only single interface rather than two or you can share view models between fragments and activity.
Method 1 : Using single interface
Define Interface as
public interface FragmentCallbackListener {
void onItemClick(View view, int position);
}
Let your Activity implement it :
ActivityA extend Activity implements FragmentCallbackListener {
#Override
public void onItemClick(View view, int position) {
....
}
}
Fragments which are attached to activity implementing FragmentCallbackListener should override onAttach() of fragment as:
public class FragmentA extends Fragment {
private FragmentCallbackListener mListener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the listener. If not, it throws an exception
try {
mListener = (FragmentCallbackListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement FragmentCallbackListener");
}
}
}
Pass same listener instance to Adapter :
adapter = new AdapterA(context, dataList, mListener);
Method 2 : Using shared view model
Define view model as :
public class SharedViewModel extends ViewModel {
private final MutableLiveData<Data> selected = new MutableLiveData<Data>();
public void select(Data data) {
selected.setValue(data);
}
public LiveData<Data> getSelected() {
return selected;
}
}
Inside FragmentA
public class FragmentA extends Fragment {
private SharedViewModel model;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
...
adapter = new AdapterA(context, datalist, model);
}
}
Inside adapter's view onClickListener :
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
model.select(view.getTag()); //or use getData(position) to return selected data
}
});
Inside ActivityA
ActivityA extend Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedViewModel model = ViewModelProviders.of(this).get(SharedViewModel.class);
model.getSelected().observe(this, data -> {
// launch the new fragment B with selected data
});
}
}
For more details, read https://developer.android.com/training/basics/fragments/communicating
Without an external library, have you considered using a broadcast?
It still requires boilerplate, but depending on your opinion can be a bit cleaner (the activity wont need to to be an instance of any interface, you don't need any 'god object' models)
In FragmentA's adapter, when an item is clicked you send a broadcast with an explicit action and the arguments as extras. In the activity you register (and unregister) a broadcast receiver (no need to alter manifest). Finally the receiver starts FragmentB as usual.
Fragment A / Adapter
Intent item = new Intent(MY_CONSTANT);
item.putExtra(MY_EXTRA_CONSTANT, position);
getActivity().sentBroadcast(intent);
Activity
private final BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int position = intent.getIntExtra(MY_EXTRA_CONSTANT, -1);
//TODO: Move your FragmentB transaction here
}
};
void onPause() {
unregisterReceiver(myReceiver);
}
void onResume() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(MY_CONSTANT);
registerReceiver(myReceiver, intentFilter);
}
You can achieve it without using Interface, BroadcastReceiver and ViewModel.
Check below code:
ActivityA.java
public class ActivityA extends AppCompatActivity {
ActivityTestBinding mBinding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_test);
pushFragment(new FragmentA());
}
/**
* #param fragment pass fragment you want to replace
*/
public void pushFragment(Fragment fragment) {
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped && manager.findFragmentByTag(backStateName) == null) {
// if fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.container, fragment, backStateName);
ft.addToBackStack(backStateName);
ft.commit();
}
}
#Override
public void onBackPressed() {
try {
if (getSupportFragmentManager().getBackStackEntryCount() <= 1) {
finish();
} else {
getSupportFragmentManager().popBackStack();
}
} catch (Exception e) {
super.onBackPressed();
}
}
}
Here pushFragment method is generalized for all fragment.
And in onBackPressed() it will check BackStackEntryCount. If there is 1 or less count that means only last fragment is in backstack and finish(); will be called and exit application. If there is >1 count in BackStackEntryCount then it will pop last fragment.
In your AdapterA.java:
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (context instanceof ActivityA) {
FragmentB mFragmentB = new FragmentB();
Bundle bundle = new Bundle();
bundle.putParcelable("single_data_key", dataList.get(getAdapterPosition()));
mFragmentB.setArguments(bundle);
((ActivityA) context).pushFragment(mFragmentB);
}
}
});
Here you already passing context of ActivityA. So you can check that if (context instanceof ActivityA) then you can call pushFragment method of ActivityA by using Type Casting.
So this is less boilerplate code you can integrate in your Android Project.

Registration with two steps, next fragment by button

I want to handle user registration in my app. I red that using fragments is the best way to handle it.
I prefer using button to move to registration finish fragment, than swype.
I have to send few field to another and finally send all of data by Retrofit.
Any solution?
You can implement a Callback to save the values on your activity.
First create the interface:
public interface ActivityCallback {
void sendData(String data1,String data2);
}
Then make your activity implements this interface:
public class MyActivity extends AppCompatActivity implements ActivityCallback{
private ArrayList<String> arrayData = new ArrayList<>();
...
#Override
void sendData(String data1, String data2){
this.arrayData.add(data1);
this.arrayData.add(data2);
}
...
}
Then on your fragment, when you decide to go to the next step:
public class YourFragment extends Fragment{
private Button nextButton;
private EditText text1;
private EditText text2;
protected ActivityCallback callback;
...
#Override
public void onAttach(Context context) {
super.onAttach(context);
callback = (ActivityCallback) context;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
...
nextButton = (Button) findViewById(R.id.next_button);
nextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
callback.sendData(text1.getText().toString(),text2.getText().toString());
}
});
}
}

Refresh the Fragment on dismiss of Dialogue fragment

There is some synch process on server that updates the database and I want to refresh the parent activity on click of dialogue dismiss to get the synched values in a view.
I have three fragments- FragmentA.java, FragmentB.java and ragmentC.java
In FragmentA.java, I have public interface OnEntrySelectedListener which have method getDialog() and
other fragment class FragmentB.java implements this interface and have definition for getDialog() method.
FragmentA.java
class FragmentA extends Fragment
{
public interface OnEntrySelectedListener
{
getDialog();
}
}
FragmentB.java
class FragmentB extends FragmentActivity implements FragmentA.OnEntrySelectedListener
{
#Override
public void getDialog(Bundle bundle) {
FragmentC cf = new FragmentC();
cf.setArguments(bundle);
cf.show(getSupportFragmentManager(), "dialog");
}
}
FragmentC.java
class FragmentC extends DialogFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
//some code here
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
view = inflater.inflate(R.layout.shared,container, false);
view.findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0)
{
getDialog().dismiss(); //Here after dismiss, I want to refresh FragmentA
}
});
return view;
}
Now I want to refresh the FragmentA on dismiss of FragmentC.
You can add an interface and callback to C to do something like this:
#Override
public void onDismiss(DialogInterface dialog) {
if (getActivity() != null && getActivity() instanceof Dismissed) {
((Dismissed) getActivity()).dialogDismissed();
}
super.onDismiss(dialog);
}
public interface Dismissed {
public void dialogDismissed();
}
Then in the main activity you can implement the interface and when you get the call you forward it to fragment A.
You could also fire a refresh event that FragmentA would listen to.

Categories