I am a .NET mobile developer and since i started working with android, i noticed that the only way i can store my event handlers of the views is through the activity file or by creating a class to hold all these event listeners. Can someone suggest best way that i can do to have the least clutter and store all the event handlers accordingly?
A bit subjective as "clutter" depends on how efficient you are at implementing your event handlers and how complex your app is.
For instance I've seen example code here on SO like...
button1.setOnClickListener(new View.OnClickListener {...});
button2.setOnClickListener(new View.OnClickListener {...});
button3.setOnClickListener(new View.OnClickListener {...});
In each case an anonymous listener for each individual Button often performing a very similar function (start activity 1, start activity 2....). The cleanest way would be to implement View.OnClickListener on the Activity itself and then use...
button1.setOnClickListener(this);
...(and so on for each Button) then get the resource id of the View passed in to the listener to identify what was clicked and what needs to be done. It amazes me how many people don't get that.
As for creating a separate class (or classes) to hold listeners, that gets tricky depending on how many activities you have going on. Maintaining the listeners separately has two downsides.
Firstly if you don't go with the model of having an Activity use anonymous listeners or implement the listener directly, that suggests you'll have a whole load of activities (which may be extended at some point) using your 'helper' class listeners. Each time you extend your Activity you need to make sure the separate class is updated to cope with it - potentially an out of sight, out of mind problem where you want something new from an Activity which your 'generic' listener doesn't handle.
The second potential problem is in the way Android works (depending on your app). An Android Activity is meant to be modular - if it displays photos or images or documents of a particular format then it should be as self-contained as possible. Having a separate class with a multitude of listeners in means that a very simple Activity meant to do a very simple task ends up loading a bloat of a class (or classes) which contains a whole load of listeners which aren't relevant.
Stick with simple - optimise the listeners for each Activity and keep them self-contained. If you feel there's any duplication going on, define your own base classes and extend from there.
It's not clear what result you want to get. As I understand, you do not want to create any Activity subclass to handle the UI events. If so, then it is really weird - how would you show those views not within an Activity?
Related
I have a question about handling click event of button.
I have already read this article
I know the difference by code, styling, readable... But I do not know the difference about performance in these two ways:
The first way:
buttonA.setOnClickListener(this).
The second way:
buttonB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// To do something
}
});
Has anyone found out this?
If there is one you shouldn't worry about it because it's that small.
Readability is much more important.
'The second' way creates one more object.
In second way you are creating new View.OnClickListener, Objects take time to create, and memory to keep them available.
I'm avoiding implementing listener in my classes, i prefer to use annonymous class (Second way), if I have to use listener in many places than I am creating field that holds it.
The first method implements the OnCLickListener class whereas the second method creates an Anonymous class.
The first method will result in your code being more organised and neat, but if you have multiple buttons, then you have to add more code to the OnCLick method.
Whereas in Anonymous classes, every time a click event occurs, a new object is created, which really doesn't affect the performance. The effect is negligible. But since the objects are dynamically created, which means the Garbage Collector should free the associated memory once the object is no longer being used.
TO summarise, there is almost negligible difference in both their performances. Deciding which one to use mostly depends on your need/requirement.
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.
This is a double question about using interfaces - namely onclickListener (and related) within an Activity.
onCreate should be short - so says the documentation - but if I have lots and lots of views all of which have onClickListeners it can get quite long. I'm worried this will cause the UI thread to timeout. Is this a problem?
Is there a best way to use onClickListener? By which I mean, is it better for the Activity to implement onCLickListener and then have a very long onClick() method? Or do the following:
mView.setOnClickListener(new OnClickListener(){
...
});
for each View? Does it really make any difference?
They mean "short" in that don't do anything that takes a long time to process in onCreate(). Anything like math computations, networks or database access, extremely large bitmaps inflations should be done in a thread. The only overhead that setting an onClickListener to a view is calling a method, setting a reference, and usually creating an object. If object creation does any of the aforementioned things, then it would be best to pre-load the object before creating it.
There's no real difference. What you choose depends entirely on your implentation and coding stye. Using an anonymous object like you showed is kind of like a "set-and-forget" style way of doing it. It's suitable if the action is unique to the button. Creating a whole new class that that implements onClickListener() would be required if there needs to be a state that persists with each click. That way, you create the object once and set all the necessary views to the single object. It may also be useful to do it in that fashion if many views do the same action when clicked.
It shouldn't bother with the loading of your activity because the code inside onClick listener is executed only when a click is made on its view.
Besides, its not a good idea to execute heavy stuff (network, database, drawable manipulation, etc.) in onCreate. In case if you really need to do such processing then off-load it to an AsyncTask which runs your code in a separate thread causing your UI (main) thread to be free.
1) I agree with Deev's answer.
2) Please note that if you choose to use the anonymous inner class solution
mView.setOnClickListener(new OnClickListener(){
...
});
You create an object for each assignment.
Conversely if you implement OnClickListener in your activity you won't create any other object. This doesn't make so much difference for a small number of object but could save some memory (and save you from GC) for larger number (and you said to have a lots and lots) of objects. Avoid unuseless object creation is suggested in Designing for Performance
I have an app with multiple activities and multiple layouts. However, one piece of layout is included on several activities. I also have a thread which updates this layout. However, when i switch activity it doesn't work. Since the layout is included the elements have the same ID's, shouldn't it just work? Or do I really need to fetch an object for each element in the layout and feed it into my thread in order to make it update the elements in a new activity?
You should run the update code for each Activity/View, although the XML included is the same, each is a different instance.
My suggestion is on Restart verify is there is any modification to do in each activity, a simple way is to each Activity extend a BaseActivity that has this code.
I include a layout for adverts in my app, but on each activity that uses it, the adverts need to be reloaded.
If I call an activity from one that is using the same included layout when I go back to the previous activity it's still there.
I guess this is what you are seeing....
So you can also save that data inside sharedPreferences (if it is little data and primitive objets or parceable objects).
Also you can extend the Application class and store the data there and update every activity inside the onResume() method. that i believe is the best way to handle this. and this is quite simple to do.
Ask google about extending the application class and he will provide tons of results on how to do it. its an easy way to pass data between activities and/or keep a reference to a single object which you will use throughout the app. Just be carefull to clear it when you wont need it anymore because it will stay in existance untill the application is finished() (which comes with the application extension living thru the whole application lifetime).
I have put the all the binding code for UI events on OnCreate(). It has made my OnCreate() huge.
Is there pattern around implementing UI events in android ? Can I add methods in View xml file and then I can put all the handler code somewhere else.
In a nutshell , I think I am asking how can I implement MVVM pattern with android app code ?
Stuff that I do:
Keep all onClick functions in the XML. Avoids a lot of clutter in the Java code.
Initialize event listeners as members of the activity class rather than keeping them in a function. I don't like too many curly braces in my code. Confuses the hell out of me.
If my list adapters get too big I keep them in a separate class rather than as a member of the activity class and then keep all view listeners there in the adapter.
To avoid creating too many onClick functions I sometimes keep one function like onNavigatonClick and then use view.getId() to see which button was clicked. As the XML is not checked for valid function calls, it leads to runtime errors if your function name is wrong.
If a particular view needs a lot of UI interaction code, I create a custom view with a GestureDetector to handle UI interactions.
I guess this is still quite basic as I haven't had much experience with Java yet.
In 1.6 and later you can specify onClick methods in your layout XML file to trim a bit of the fat. I generally just hide it all away in a initUi() method that I have my onCreate method call. This way at least the onCreate is easier to read.
Lots of good answers to this already. :)
If you're using Android 1.6 or later you might find the new fragments API helpful for organizing and partitioning your activities into several logical units.
onCreate is usually the best place for calling setContentView and setting up listeners, but the code for handling the user interractions normally goes in onClick, onTouch, onKey etc. routines.
Maybe if you posted your code we could see what you've done?