I'm facing an issue which hopefully you can help me to fix. In my Android app, I display a Snackbar using the usual way (Snackbar.make().show()). However, I also have to deal with configuration changes (like orientation changes from portrait to landscape).
Now if the configuration changes, the Snackbar disappears, which is nothing I wouldn't expect. I had the same issue with ProgressDialog and AlertDialog, which I solved by using a custom subclass of DialogFragment.
I also had this issue with my AsyncTasks which I solved by using a custom subclass of Fragment which I retain (setRetainInstance(true) in onCreate() of the Fragment) and which keeps a reference to my AsyncTask. In both cases, each Fragment has a callback interface which the Activity has to implement and I set/unset the callback during onAttach()/onDetach().
However, Snackbar seems to be different because it is attached to a View instead of a Context like for example the ProgressDialog (in getDialog() of my DialogFragment I can use new ProgressDialog(getActivity())).
So when and how shall I display a Snackbar after a configuration change? Is using a Fragment the way to go or should I try to work around this by having some private variables on my Activity which I save/restore via the savedInstanceState?
Since no suitable answer was provided and I had to meet a deadline, I now went with the following solution:
Create a activiy base class which extends AppCompatAcitity and from which all my activies inherit
In the activity base class, create a bunch of instance variables to store information about the Snackbar (isShowing, identifier, message, action, arguments)
In the activity base class, create a method to show the snackbar, giving it all the previously mentioned variables
In the activity base class, use onSaveInstanceState and onRestoreInstanceState to save/restore the previously mentioned variables
If the Snackbar was showing before the configuration change, the boolean will be saved and restored and I can use it to create a new Snackbar with the same configuration in onRestore() of my activity base class
When creating the snackbar, I use the snackbar.setCallback() to set a callback where I check if the snackbar was dismissed and if so, I change the isShowing to false
When setting up the snackbar, I set the action to call a method in my activiy base class using the identifier I previously provided as an argument to check which Snackbar is was clicked
Related
In my fragment I have a 'dismiss' button that should behave in a different way dependent on which Activity called its parent activity (say TutorialActivity).
In the TutorialActivity I am already determining which Activity called it. How to pass that data down to the fragment?
My fragments reside in a PagerAdapter and I wouldn't like to need to pass this info as a 'newInstance()' parameter every time, as it seems an overkill, taking into consideration that this parameter would be the same for each fragment in my FragmentStatePagerAdapter.
You can access the variable from Tutorial Activity by making this variable public. Suppose variable name is parent. You can access it by using instance of TutorailActivity (suppose instance of Activity used in fragment is mTutorialActivity) then it should be like mTutorialActivity.parent.
But you need to pass instance of TutorialActivity as it may be used for other purposes also like fetching strings from strings.xml and other purpose. So it would be beneficial to pass Activity instance instead of variable.
What I ended up doing: I implemented said "different behavior" in the TutorialActivity itself, having moved the dismiss button up from the fragment. Then a simple onClickListener and a switch statement inside of it.
In android app, having a few activities with multiple fragments.
Those activities or fragment could be running alive even if it's not on the top of the backStack, and receiving notifications from different services.
When some event happens it is required to show a dialog to communicate with user. The activity or fragment on top of the stack may not have the handler for that event. Any other activity or fragment who is interested should react to open one dialog to the user.
The problem is the listeners in the activities and fragments to handle the events independently don't know if there has been already the same dialog displayed.
What is best way to tell whether the handler should open the dialog or not?
Since this dialog is same for the same event so it may help if could have it as a singleton.
Anyone have suggestion how to make the dialog a singleton for this type of situation?
You can't make Dialog singletone, because Dialogs are linked with current view. And your current view may change - dialog may be sown from different instances of the activities (one or many).
But you can implement a simple singletone class to store all dialog data - save data into onPause and retrieve it in Dialog's onCreateView.
So you will get singleton instance with all data, but Dialogs may vary according to current view.
Also you can store a weak link to the shown dialog in that singletone class. Using such method, you can detect is your dialog currently shown or not.
I'm new to android programming.
I just try to save the state of the ListView in my fragment. For that I follow headless fragments (fragment which has no UI). In this fragment, I save the data, used in the ListView, and starting the headless fragment from the main fragment (the one which has the UI).
Now I got the exception:
java.lang.IllegalStateException: Failure saving state: RetainedFragment{4161f850 #1 work} has target not in fragment manager: JobOpeningFramgent{41601c00}
As far my concern, this is happening when I'm trying to replace the fragments with another one in the DrawerLayout.
Please temme the cause of this exception, for better understanding.
Thanks.
Boopathy.
Here's a workaround:
put this in the fragment that causes the problems:
#Override
public void onSaveInstanceState(final Bundle outState) {
setTargetFragment(null, -1);
...
and remember to set it to the real target fragment when you need it.
I'm not sure what do you want to save and where do you want to save it.
The official docs state that: "A Fragment represents a behavior or a portion of user interface in an Activity."
Using a Fragment as a container of another Fragment's UI state is generally a bad idea.
If you want to persist some values throughout the activity lifecycle (that includes screen rotations) just override onSaveInstanceState method. If you want to store some variables even after activity life-time use singelton class or Preferences, and if you want to store your values even after app life-time use SharedPreferences
Please elaborate on what do you exacly want
From my activity I call showDialog(0) and then in the switch of the method onCreateDialog I would like to access a variable from the parent activity. It doesn't seem to work though. I've tried
this.neededVariable
or
((MyActivity)dialog.getOwnerActivity()).neededVariable
but they don't seem to work. Any ideas? It might be something simple which I'm not getting cause I'm very tired :)
you can pass the value of that variable to your dialog in setArgumenet, or you can use Fragment Callback to communicate the Activity, here is the example of callback
When you are in dialog you should use dialog context to interact with your dialog and when you want your Activity context you can use your activity name like :
YourActivityName.this
here is a sample that i've used in dialog code to access a TextView inside of the parent activity :
((TextView)DayReportActivity.this.findViewById(R.id.edtDailyCPCode)).setText(CPCodeText);
I has a view that is create by
this.vehicleListUI = new GameUIVehicleList();
this.vehicleListUI.attachGameEngine(myGameEngine);
This work fin unto the android destroy and restore the view.
The Android can recreate the view by use the empty constructor,
but my problem is for this GameUIVehicleList will work I most also have the myGameEngine
object set to the GameUIVehicleList
The myGameEngine is not Serializable and can't be this to ( Is a part of UI )
Exist this a way to restore my View fully by reattach the myGameEngine object
to a create view.
This will also be good for enable a lot of "new GameUIVehicleList()" into a XML layout file.
EDIT:
I don't know if this is to some help but way I has this problem from begin is
I use a android.support.v4.app.FragmentActivity and this keep to destroy and recreate
my View object. I can also fix this by override some method in android.support.v4.app.FragmentActivity that is invoke while FragmentActivity is recreate/crate a fragment and for this set the need value from my Activity that hold the need data.
Destroying and re-creation of Activity (and views) usually happens on configuration change (most often screen orientation change). You may want to check if this article helps and onRetainNonconfigurationInstance()/setRetainInstance() would not be the cure for your problems.
If myGameEngine is not Serializable or Parcelable, I do not believe it is possible to do this reliably.
However if it is ok, for myGameEngine to sometimes not be recovered you can extend the Application class with your own custom MyApplication class which contains the variable myGameEngine then in your onCreate you can get the myGameEngine that saved in your application context.
MyApplication app = (MyApplication) this.getApplicationContext();
this.vehicleListUI.attachGameEngine(app.myGameEngine);