What is the best way to handle DialogFragment callbacks? - android

I've been using DialogFragment to handle Dialogs on an app.
I've read this which gives some examples about how to use it, but it always uses things like:
((FragmentAlertDialog)getActivity()).doPositiveClick();
((FragmentAlertDialog)getActivity()).doNegativeClick();
I don't really like this implementation as it obliges a cast to a pre-known Activity so it's not very robust.
I also know that passing and storing a callback inside the FragmentDialog isn't a good option because if it references an Activity, after rotation for example, that activity could have been destroyed... and the callback is not updated.
Also updating the callback when an activity passes onResume is also not a very viable option, as it had to know which Dialog is being shown and set a callback related to it making the logic a bit tricky on larger apps.
So what implementation do you suggest to avoid casts while retaining always the most up-to-date callback?

You've enumerated the reasons why callbacks can't be used, very eloquently. Unfortunately, I think the cast (or something similar) is unavoidable. The whole paradigm is rather awkward, frankly.
You could use an interface, if you plan to share a dialog fragment between multiple activities.
((IXyzDialogHost)GetActivity())->onSomethingHappened()
There's something to be said for that approach, I suppose. I can't say I've used that approach myself, personally, but thinking about it, I might be tempted to do so moving forward. At least you can enforce a contract on the calling Activity with an appropriate static DialogFragment.Create method, which deals with the setting of the bundle the fragment manager transaction, and other unpleasantries:
class XyzDialogFragment {
{
public static DialogFragment Create(IXyzDialogHost activity, ...)
{
...
}
}
But there's still a cast.

Related

Android Model-View-Presenter(MVP) How to Return Long-Running AsyncTask

I am somewhat new to Android, and I am writing an app. I am getting to the point where I am starting to more thoroughly test my code, and therefore, I would like to implement the MVP design strategy since it adds more testable layers to the code. One of the supposed benefits of using MVP that I can not seem to understand is how it helps with running AsyncTasks as they are performed dynamically. Since you want to avoid any Android specific components in your Presenter class, how are you supposed to reference the Activity that utilizes the AsyncTasks? Tutorials about MVP show the Presenter object having methods that take in an Activity as a parameter and return to it; however, if your AsyncTask takes a long time and your Activity has been destroyed through something such as rotation change, how do you return to the proper Activity? I currently store my AsyncTask in a Fragment so that it is saved on Orientation Change. I am having a hard time finding a workaround that implements the MVP practice.
To answer your question, there isn't much you can do to avoid passing Android classes to your Presenter class. But instead of passing the Android object as a parameter, add a method to your View class that returns it (e.g. getActivity()).
That said, I strongly suggest you use a Loader instead of an AsyncTask. Loaders were designed specifically for your use-case. They can also run in the background but their lifecycle is tied to the lifecycle of an Activity or Fragment.
If you switch to Loaders, add a method like getLoaderManager() to your View interface.
If I dont miss-understand your question, your are trying to use retained non-UI fragment for long-runing task, right?
Here is my suggestions in your case:
Make ActivityView interface for your Activity
Using WeakReference<ActivityView> to refer your activity inside your Fragment Presenter (to avoid memory leak issue)
When Activity re-created, try to get your retained fragment and reset your Fragment Presenter's ActivityView. You can look at this Google Example to know how to deal with loading data while configuration changed.
In conclusion, just use WeakReference to avoid memory leak issue, and try to re-set your Presenter'sview when activity is recreated

Fragment callbacks explosion, how to deal?

I am creating my app with using fragments. I have something like main activity, it has FrameLayout as root layout to hold fragments.
After much thought I have decided to separate my application logic in several parts, for example : MainActivity is responsible for app basic navigation (MainPageFragment, CategoryListFragment, ProductListFragment, ProductDescriptionFragment), AuthActivity is responsible for autherization, registration (SignInFragment, RegistrationFragment, RecoverPasswordFragment).
A little about my app. If you have recommendation or don't agree with app structure, I would be grateful for any critics.
What is the problem, as you can see my MainActivity has many responsibilities. There are four Fragments now but it can be more in the future.
Lets consider next situation. In my MainActivity I have MainPageFragment and this fragment in turn of course has some views. And on click event I need to change fragment, for instance from MainPageFragment to the CategoryListFragment. In this case I have several ways to handle clicks or other events from framgents.
The most common way is to have activity implements callback interface defined in fragment class as nested class inteface. This approach is quite good and easy to use. But what if my host activity has to handle multiple callbacks from fragments, to say more, there can be more than one callback from single fragment, class(activity) declaration starts growing, class body too. What are another possible approaches to solve this problem.
You can handle all clicks, events directly inside fragment (start activity, replace framgent......) you can do this painless, but for me personally callback approach looks better, but maybe there is nothing bad, and I can use this approach.
Use one or several interfaces for getting information from fragments. For example create class CallbackEvent for holding such info as framgentId, eventType .... Using this approach we can reduce interfaces and methods, but Activity class body can become larger in first approach.
Use something like EventBus pattern to communicate between app components via third party service.
Of course there are some other ways to do this, but I have described most popular.
Please suggest, or just explain how to do you solve this problem in your apps, what approach is better, how to built this communication easy to maintain.
I am grateful for any advice,critics in advance.
If your app becomes more complex using the callback pattern will get messy, especially if fragments need to communicate with fragments. I'd only use that pattern for apps with low complexity (activity, one or two fragments).
Clicks, events etc. should be handled inside a fragment if whatever happens stays within the fragment. Don't replace a fragment from within the fragment, that's the Activity's responsibility. It might look easier to just do a getActivity().someMethod in the fragment but this leads to hard to maintain code. You might understand now what it's doing but will struggle in half a year.
This approach looks messy to me too (similar to 1.)
That's the one I'd recommend. I'm using EventBus (https://github.com/greenrobot/EventBus) but there are alternative implementations like Otto (https://github.com/square/otto) and I've never looked back to the times when I used the callback pattern. Using an EventBus decouples the communication between the different components and your code becomes much simpler and leaner. However you need to be careful with that approach since there are some pitfalls. One is that it gets much easier to communicate from any component to any other component which could lead to even messier code than the listener/observer pattern. Another one is that events are asynchronous compared to synchronous listener calls so you need to make sure you're only receiving the "right" events at the right moment in the component's lifecycle. The main advantages of an EventBus approach are IMO:
A message is always an object forcing the developer to code object oriented compared to the more functional listener method calls
It decouples the different components. Publisher and subscribers don't have to know about each other. Decoupling the components will make your code much leaner and easier to read (and maintain).
It can be used by arbitrary components. E.g. I replaced all LocalBroadcastManager calls by EventBus messages (EventBus is MUCH faster that using a LocalBroadcastManager). Being able to communicate between arbitrary components is especially convenient if the components can't access each other directly (like a Dialog and a Preference object)
I have two rules of Fragment - Activity separation.
One is logic. Anything that deals with View (layout expansion, display, listeners, etc) should go inside a Fragment. Important background processes (http requests, file reading, image processing, etc) should go inside Activity. Part of the reason is explained in my second point:
Lifecycle. Activity's lifecycle outlasts Fragment's. Fragment is also fragile it doesn't even retain its views. And this is the reason Fragment should be decoupled from Activity. Listeners and callbacks are tight coupling and they are the cause of countless null pointer exceptions when some process tries to update a View of a Fragment that has called its onDestroyView. Having said this I'd suggest Publisher - Subscriber pattern like Event Bus where you can plan a message delivery in which it gets digested only when a publisher (which in this case corresponds to Fragment's view) is available.
The numerous click listeners you have are related to how you design your UI. Moving code around doesn't really help much, unless you trim down your layouts.

Android Best Practice - Communication between Activity and Fragments

Hope you guys can clarify something for me.
I've been using Android for about 6 months now and I'm still confused about the best way to communicate between Activity and Fragments. I've already read the the info on the android developer site.
Fragment to Activity
Right now I know with 100% absolute certainty that an interface is the best way to communicate from Fragment to Activity. I.e. creating an interface in your Fragment and letting your Activity implement it. This way you can call the method from your interface inside your Fragment and have it handled by the Activity (which implements the interface).
Activity to Fragment
Here's were I'm not sure. The android developer site says that in order to communicate with a Fragment you have to put your objects in a Bundle.
Bundle bundle = new Bundle();
bundle.putInt(SOME_IDENTIFIER, myInt);
Now I've been know to use a Singleton class every now and then when I have quite some functionality that I can separate. Say I have a Singleton called PersistenceService where I handle all of the persistence related stuff, e.g. saving something in the SharedPreferences. The PersistenceService will then hold methods like putMyString(String key, String myString) or putSomeObject(String key, SomeObject someObj). This way a class doesn't have to handle persistence itself but can just call the PersistenceService to do it.
Now say I have to update something in my Fragment, a TextView or something.
This is what I do:
String myString = PersistenceService.getInstance(getActivity()).getMyString(someKey);
textView.setText(myString);
I pass in a context (getActivity()) because I need it to get the SharedPreferences.
Now my actual question is:
Do I retrieve my data in the Activity and pass it to the desired Fragment through its Bundle? Or do I simply reference my Singleton right in my Fragment and access the data there directly.
I'm not stuck or anything, but I'd like to know what you guys would recommend.
Any advice, remarks, info etc. is greatly appreciated.
This is a very broad question, and as the pragmatic thinking and learning book says, the answer to most questions in software is "It all depends!".
And it really does, it really all depends, there's no hard rule in software, "always" and "never" are very powerful words that shouldn't be used in software, so, saying always go for "Bundle" info or Never go for a Singleton is a little bit stupid specifically in software, so, instead of telling you exactly what to use, ask your self what would fit better in your needs taking on count things like, scalability, extensibility manageability, etc. For example:
If you go for Bundle, you give some flexibility to your fragment, you are creating some kind of independent component ready to work with whatever information you provide, on the other hand, if you know that you need that fragment only in that place, and the information you will pass is somehow complex(can't be passed using a bundle), why complicating so much? Just go for the Singleton if it does the job simple and clean.
I hope my point is well explained here, there's no hard rules for one way or another, just be as diligent as possible and don't go one way or another just because of laziness or negligence, instead be analyst if it's worth going one way or another based on your needs, and always take on count that not because you went that way this time it will be true for ALL your scenarios.
Hope it Helps!
Regards!
I use bundle when I want send data from fragment to fragment (from fragment to activity by interface, from activity to fragment by bundle).
If data is used in all fragments singleton is the best way, sometime I use also a istance of data objcet in activity that I manipulate in fragment by public methods of activity but I don't think that this is a best pratic.
Please understand that 2 fragments can’t directly communicate with each other, They will need help of the activity under the context of which they are created. Using an interface :).
Implement the interface in a fragment
interface StartCommunication
Define the interface in the activity whose context fragment is using
public class MainActivity extends Activity implements
SendFragment.StartCommunication

Are there any downsides to calling Activity.finish(), startActivity(), startActivityForResult() anywhere else besides in the Activity itself?

I have a project that I am working on that is currently calling the Activity methods just about all over the place. (eg. my CameraActivity is calling startActivityForResult() in its JpegPictureCallback, another activity is having startActivityForResult() called in one of its Views, and yet another has one of its button's onClickListeners call finish() )
I am new to Android, but some of this practice seems odd to me. Especially when I have had to explicitly give a child view or onClickListener the parent Activity just so it can call such methods. Usually when I have to go out of my way like that to make something work, there is usually a better way to do it.
Also calling startActivityForResult() in one class and having onActivityResult() returning in another class seems counter intuitive. It seems to not form a logical flow of information.
Specifically my questions are:
Is there a performance impact to calling Activities in this way?
Is this proper coding style? (Both personally, but specifically according to some well-defined guidelines i.e. Android's dev guidelines)
No there is no performance impact in calling activities this way.
Yes this is the standard coding style. Refer the link below for the coding standard.
For detailed info check : http://developer.android.com/training/basics/intents/result.html

Android: is it possible to refer to an Activity from a 2nd Activity?

This is a pretty simple question, but I have been unable to find anyway to accomplish what I am trying to do...
I want to launch a new Activity to display some complex information. Because of the complexity, it is undesirable to serialize the information into the intent's parameters. Is it possible for the the new Activity to get a reference to the launching activity, so it can call its methods?
If you use a custom application class, you can store information that will be kept between the activities.
See a tutorial here for instance.
The lifetime of an Activity cannot be depended upon. In this case, one way of sharing data is to have a singleton which holds the data to be shared between the two activities.
You can add a public static field to the first activity containing this (the first activity).
But beware that the first activity could be destroyed by Android while you are using the second activity, so you will have to implement a fallback method if the first activity is destroyed.
And don’t forget to unset the public static variable in the onDestroy() callback of the first activity or you will leak memory.
Is it possible for the the new Activity to get a reference to the launching activity, so it can call its methods?
Please do not do that. Android can and will destroy activities to free up memory.
Complex information like you describe should not be owned by an activity. It should be held in a central data model, like you would in any other application. Whether that central data model is mediated by a Service or a singleton or a custom Application object depends a bit on the type of data, caching models, risks of memory leaks, and so on.
You can make your complex objects public and static in ActivityA, and access them in ActivityB like this:
MyCustomObjectType complexFromA = ActivityA.complexObject;
this will work, however while in ActivityB, you can't always be sure that static objects from ActivityA will exist(they may be null) since Android may terminate your application.
so then maybe add some null checking:
if(null == ActivityA.complexObject) {
//go back to ActivityA, or do something else since the object isn't there
}
else {
//business as usual, access the object
MyCustomObjectType complexFromA = ActivityA.complexObject;
}
You could also use a Singleton object which extends Application. You would have the same problem when Android terminates your application. always need to check if the object actually exists. Using the Singleton extending Application approach seems to be the more organized way - but adds more complexity to implementation. just depends what you need to do and whatever works for your implementation.
You should create a separate class that both the activities can use.
public class HelperClass{
public void sharedFunction(){
//implement function here
}
}
I would recommend staying away from static variable in android. It can cause some unexpected behavior.
Use getParent() from new activity and call parent's method
Android Activity call another Activity method

Categories

Resources