Can an Activity be notified when a fragment is killed? - android

Is there any function that is called when a fragment is killed? Or can an Activity listen for such changes like fragment removal etc?

here are some of fragment life cycle methods names are pretty self describing
you can call your activity's method from those bellow
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onDetach() {
super.onDetach();
}
#Override
public void onStop() {
super.onStop();
}
#Override
public void onPause() {
super.onPause();
}
ok here is a way to add listener to your activity.
1 create Callback interface like this
public interface CallBack<T> {
void onCall(int key, T body);
}
2 make your activity to implement it e.g.
public class MyActivity extends Activity implements Callback
once you do that you will need to implement onCall method in your activity class
onCall is a method that will be called from fragment
3 in your fragment class ad a member variable
private Callback<TypeYouWant> callback;
4 create a setter for callback
public void setCallBack(Callback c){
this.callback = c;
}
5 go to you activity and setCallback, since your activity knows about your fragment therefore you have reference to it. at least you can get it with getFragmentManager().findFragmentById() . in activity's onCreate method add this
myFragment.setCallback(this) //note you can pass **this** because your activity implements `Callback` interface
6 last step , in your fragment's onDetach add
#Override
public void onDetach() {
super.onDetach();
if(callback !=null){
callback.call(some key, some T type value);
}
}
so that's it whenever onDetach called in fragment your activity will get callback

Related

How to implement an interface in Fragment from a non parent Activity?

I have not found a clear solution anywhere on stack for this.
Here's my basic set up
public class Activity1 extends AppCompatActivity
{
private OnAttributesUpdatedListener onAttributesUpdatedListener;
public interface OnAttributesUpdatedListener
{
public void onAttributesUpdated();
}
public void setTargetFragment(Fragment fragment)
{
this.onAttributesUpdatedListener = (OnAttributesUpdatedListener) fragment;
}
private void whenFinishedSomethingCallback()
{
onAttributesUpdatedListener.onAttributesUpdated();
}
}
public class Fragment1 extends Fragment implements Activity1.OnAttributesUpdatedListener
{
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view) {
if(rivalButtonClick == 0)
{
Activity1 activity1 = new Activity1();
activity1.setTargetFragment(Fragment1.this);
startActivity(new Intent(getActivity(), activity1.getClass()));
}
}
});
}
I get a null pointer exception and crashes on : onAttributesUpdatedListener.onAttributesUpdated(); because for some reason my listener never gets set properly. What's the proper way to do this?
You need to set the listener at start of the fragment onCreatView() or in onActivityCreated() only if the Desired Activity is a parent Activity of that particular fragment. Below is an example .
public class Activity1 extends AppCompatActivity {
private OnAttributesUpdatedListener onAttributesUpdatedListener;
public interface OnAttributesUpdatedListener {
public void onAttributesUpdated();
}
public void setListener(OnAttributesUpdatedListener onAttributesUpdatedListener) {
this.onAttributesUpdatedListener = onAttributesUpdatedListener;
}
private void whenFinishedSomethingCallback() {
if(onAttributesUpdatedListener!=null)
onAttributesUpdatedListener.onAttributesUpdated();
}
}
public class Fragment1 extends Fragment implements Activity1.OnAttributesUpdatedListener
{
#Override
public void onAttributesUpdated() {
// Do your stuff here
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
((Activity1)getActivity()).setListener(this);
}
}
Read about fragment Life cycle to make use of getActivity(). also remove the listener when fragment is destroyed .
Use LocalBroadcastManager for communicating between in case the Fragment exists in other Activity.
At first create an Interface like this:
public interface Listener{
void doSomething() }
Then implement this interface in your activity.
And also add
Listener listener
In your fragment
And in onAttach method in fragment use this
listener=(Listener)activity
Then call listener whenever you need .

How to access viewpager's fragment from activity

Suppose such an scenario, we have an activity and 3 fragments, like so: MyActivity Frg1, Frg2 and Frg3. Frg2 and Frg3 are embedded into a viewPager. My needs is to trigger Frg2 from Frg1. I made an interface TriggerActivityFromFrg1 and MyActivity implements it, when press button in Frg1 I call (getActivity) triggerActivityFromFrg1.trigger() and method trigger() is called in MyActivity, the problem is how to trigger Frg2 from activity?
I'd like to make somehow an interface between MyActivity and Frg2.
p.s. I don't want to use eventbus.
Have your Frg2 class also implement the interface:
public class Frg2 extends Fragment implements TriggerActivityFromFrg1 {
and implement the method
#Override
public void trigger() {
if (getView() != null) { // see comments below
// TODO logic here
}
}
Add a field to your activity to keep track of the target fragment:
private TriggerActivityFromFrg1 mTarget;
Add the register/unregister methods to the activity:
public synchronized void registerTriggerTarget(TriggerActivityFromFrg1 listener) {
mTarget = listener;
}
public synchronized void unregisterTriggerTarget(TriggerActivityFromFrg1 listener) {
if (mTarget == listener) {
mTarget = null;
}
}
Make the trigger method in your activity like this:
public void trigger() {
if (mTarget != null) {
mTarget.trigger();
}
}
Override onAttach() and onDetach() in Frg2 to register/unregister:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((MyActivity) activity).registerTriggerTarget(this);
}
#Override
public void onDetach() {
((MyActivity) getActivity()).unregisterTriggerTarget(this);
super.onDetach();
}
Congratulations, you just built your own mini event bus.
There's a reason you have to add all this code, and that's because ViewPager won't create fragments until it needs them. Also it decouples MyActivity from Frg2.
Another thing to keep in mind if extending FragmentPagerAdapter is that the fragment will stay in memory even if the view is destroyed, so make sure you check that the fragment has a valid view, i.e. if (getView() != null)

EventBus OnEvent() is not getting called

Hi Iam using Event bus to pass data from one fragment to another Fragment
From fragment-1 I am doing as below
#Override
public void onPause() {
bsValues = new BoreShaftValues(strtext, strtextshaft);
bus.post(bsValues);
super.onPause();
}
In Fragment-2 I registered bus in OnActivitycreated
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
bus.register(this);
}
Then I placed OnEvent() method in fragment-2
public void onEvent(BoreShaftValues event){
boregradeselect.setText(event.getBoreData());
shaftgradeselect.setText(event.getShaftData());
}
Below is my BoreshaftVales class
public class BoreShaftValues {
private String boredata;
private String shaftdata;
public BoreShaftValues(String boredata, String shaftdata){
this.boredata = boredata;
this.shaftdata = shaftdata;
}
public String getBoreData(){
return boredata;
}
public String getShaftData(){
return shaftdata;
}
}
But this OnEvent() method is not getting called at all. Am i doing it the rightway?
I typically try to tie EventBus back to the Activity and yet enable it to be loosely coupled. So in the Fragment lifecycle I register EventBus in the onAttach and unregister it in the onDetach methods in the fragment.

Otto Subscribe method not called from Activity to Fragment in Another Activity

This is my first activity where Im making a post call. The bus provider is the default one in the otto sample app.
void openNextActivity()
{
manager.bus.post("Hi");
// Intent to my next Activity
}
This is my fragment in another activity where im subscribing for the data. The bus received is the same, however the subscribe method is not being called.
public class ProductListFragment extends BaseFragment {
String LOG_TAG = ProductListFragment.class.getCanonicalName();
public static ProductListFragment newInstance() {
ProductListFragment fragment = new ProductListFragment();
return fragment;
}
public ProductListFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().invalidateOptionsMenu();
}
#Override
public void onResume() {
super.onResume();
BusProvider.getInstance().register(this);
}
#Override
public void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}
#Subscribe public void onPostRecived(String s) {
Log.d(LOG_TAG, s);
}
}
There are no errors on anything being received, however if I put a button onclick on the fragment and post some content from there, the subscribe method is being called. For eg.
#OnClick(R.id.makePostCall) void call() {
BusProvider.getInstance().post("Hi");
}
I'm getting the appropriate log on this call. Any idea where the code is going wrong?
it seems you subscribe your second activity's fragment after sending stuff to event bus. Consider changing your logic
u send msg before intent;the BusProvider id registered after intent;
just try:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
BusProvider.getInstance().post("Hi");
}
},3000);

let activity know when fragment is finished an operation

I have an activity with two fragments.
Fragment A does a complex operation during onResume(), and Fragment B needs fragment A to be finished the complex operation, or else user interaction with Fragment B will cause a crash.
I want to put a progressbar spinning object in this activity until Fragment A is complete, and then reveal the layout with Fragment A and Fragment B side by side.
But I am unsure how to expose the completion of Fragment A's onResume to the activity.
In Fragment A I do have a fragmentlistener set up
public void onAttach(final Activity activity) {
super.onAttach(activity);
try {
this.mListener = (TopicListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.getClass().getName()
+ " must implement TopicListener");
}
}
But now what, thanks.
As suggested on Android Developer here, I would suggest you to not couple the fragments and use a callback through your activity class.
do this:
public class MyFragmentOne extends Fragment{
#Override
onResume()
{
//Do the complex task
((MyActivity)getActivity()).fragmentTaskCompleted();
}
}
public class MyActivity extends Activity
{
public void fragmentTaskCompleted()
{
//Show second fragment
}
}
Use your callback to send you to the activity.
Example of using callbacks with a map fragment
private MapListeners mLocation;
public interface MapListeners{
public void onMarkerClick(Marker m);
public void onLocationChanged(Location location);
}
#Override
public void onAttach(Activity activity){
super.onAttach(activity);
try{
mLocation = (MapListeners)activity;
}catch(ClassCastException e){
throw new ClassCastException(activity.toString() + " must implement OnMarkerClick and OnLocationChanged");
}
}
public boolean onMarkerClick(Marker marker) {
//marker is clicked so send a call to the activity like this
mLocation.onMarkerClick(marker);
return true;
}
In the activity make sure you implement the interface, in this case it would be MapListeners
then when a marker was clicked the onMarkerClick method you created gets called
public void onMarkerClick(Marker m) {
//do something
}

Categories

Resources