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.
Related
I am trying to create a library, lets call it L. A company has an android app, say A.
L can be linked to A such that in the codes of A, the dev just needs to add something like:
L l = new L("client_id")
l.startTrack();
Now L should be able to track all clicks that happens in A and pass to a server for logging. AppSee is a product that is already doing this.
I am wondering how can i intercept every user action to get the action target name (button title? textfield?)
Thank you!
What you are asking is EventTracking, like in GoogleAnalytics. But the approach you are doing is different. In Google analytic one needs to start event to event tracker. Like say you have a 3 buttons and you need to track each button separately, there you put 3 separate events trackers.
If you want to track all the events going through the activity you need to implement Activity's onInterceptTouchEvent(). Whenever a touch event happens in an activity, it passes through the said method above.
As Google says
Implement this method to intercept all touch screen motion events.
This allows you to watch events as they are dispatched to your
children, and take ownership of the current gesture at any point.
with caution
Using this function takes some care, as it has a fairly complicated
interaction with View.onTouchEvent(MotionEvent), and using it requires
implementing that method as well as this one in the correct way.
For more Event details, look here.
OnClickListener is a Interface. so you can implementing it's in any class
It's pretty easy. Since every control on the screen is a subclass of view, you can do something like this:
public static void logClicksOnMe(View v){
v.setOnClickListener(new View.OnClickListener{
#Override
public void onClick(View v){
//TODO Log code
}
});
}
Obviously that would destroy the listeners you already set on such object, but you can do something like this:
public static void setLoggedListener(View v, View.OnClickListener listener){
v.setOnClickListener(new View.OnClickListener{
#Override
public void onClick(View v){
//TODO Log code
if(listener!=null) listener.onClick(v);
}
});
}
The developer will have to set the listeners manually, but he already has to, so neither the workload or the code should change much. The advantage over the onInterceptTouchEvent() activity interface is that you can absolutely control which view are gonna be tracked and the developer is not constrained to use your abstract activity (let's say he already is using other abstract activities from third parties, like SlidingActivity or things like that.), so the maintenance and implementations efforts are pretty small.
Not exactly, actually there is something more easier, you can ask them to inherit there activities from your activity
eg. A extends L;
Do this in following steps.
1. Create the library(say L is com.click.counter), with event handles counter like explained in many reply above, using view.onclicklistner. In onclick event, The only difference is use package name. As context is of the app which is calling the library, you can use
Context::getPackageName
http://developer.android.com/reference/android/content/Context.html#getPackageName%28%29
2. onclick events, you may log and sync in one go, at end of day/scheduled time, or on every click. you may use httphandler for that
See
https://cloud.google.com/appengine/docs/go/gettingstarted/helloworld?hl=en
2. Create a test apk(A),add the library as dependency in gradle.
dependencies {
compile 'com.click.counter'
}
3. Inherit all the activity in test apk from class A
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 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?
In Android there seems to be 3 common ways of handling button clicks, how much difference is there between the methods? And are any of them 'better' in some way?
The three methods I keep seeing are:
Anonymous class
Find the button by it's ID, then pass a new anonymous class to setOnClickListener, e.g. in onCreate
findViewById(R.id.myButton).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// .. Whatever
}
});
Implement OnClickListener
Implement OnClickListener and pass this to setOnClickListener, then use a switch statment based on the button ID, e.g. in onCreate
findViewById(R.id.myButton).setOnClickListener(this);
and implement onClick like
public void onClick(View v) {
switch(v.getId()) {
case R.id.myButton:
// ... whatever ...
break;
}
}
Use onClick XML atribute
In the XML layout for your activity, instead of giving your button an ID, use onClick like this:
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:onClick="buttonClicked"
android:text="Button" />
Then have a buttonClicked method in your Acitiviy like this:
public void buttonClicked(View v) {
// ... whatever ...
}
At the moment I tend to use the XML attribute, but that's just because it involves the least amount of code. When should I use the other methods?
The first two are the classic approaches. Which one you prefer is more of a general Java question than an Android question.
The third one was added later to make things easier.
Setting up a click listener on a button is very common task, but it
requires quite a bit of boilerplate code. One way to reduce the amount
of boilerplate is to share a single click listener between several
buttons. While this technique reduces the number of classes, it still
requires a fair amount of code and it still requires giving each
button an id in your XML layout file. With Android 1.6, none of this
is necessary. All you have to do is declare a public method in your
Activity to handle the click (the method must have one View argument)
Source
I've really always seen it as preference. I'm not sure there's any performance advantage to either other than the last two methods may be slightly faster since they're not creating objects at runtime.
The first option isolates the code to the single button so it's very easy to debug since you know only that code will be executed when that button is clicked. However, many buttons can cause initialization methods to expand to large sizes.
The last two methods put all button handling in one place which can be convenient and cleaner at times, but with many buttons you have to decipher which button was tapped by the user via the v.getId() method.
The last option allows you to easily specify specific methods for specific buttons so you can separate them out like that, but again you'll have many methods used for single purposes.
I've always used the inline method (anonymous class) for custom dialog windows that have buttons since it keeps the code with the rest of the dialog rather than in an activity or class. I just initialize the buttons of the custom dialog when I override the onCreateDialog.
I implement the OnClickListener on the Activity if the buttons are on the main window.
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?