In Android/Java, if I have a button, I can add a click listener two ways -
1)
Button button = findViewById(R.id.my_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
-- or --
2)
Button button = findViewById(R.id.my_button);
button.setOnClickListener(this);
I sometimes prefer option #2, mainly because of brevity, but am curious about the performance considerations of essentially passing the entire class/context to the Listener...
Does anyone have any thoughts/experience in regards to this ?
I think both methods are valid
All depends on what you want to do. For example, if you have many buttons on a screen and you choose to use the first option, for each button you'll need a new object to handle the click. In contrast to the second option, with the same object (activity) as a listener, you'll consume fewer resources because it would be creating fewer objects (Java).
On the other hand, remember that the view holds a reference to context.
The latter approach is obviously more efficient: All it does is passing a reference to this, an already existing object, to setOnClickListener, which will then be used to call onClick.
The first approach is slightly less efficient as it creates a new object, an instance of an anonymous inner class. The creation of a new object and the existence of an additional class is the main difference.
You might also produce some overhead using the first approach when dealing with variable transactions between the surrounding class and the anonymous inner class. Most issues, e.g. threading related problems, affect both approaches.
Summing up, there is no real performance difference. If you are going to create a lot of buttons, you should consider sharing a single instance of a View.OnClickListener.
I usually prefer anonymous inner classes (up to a limited size), because it separates the code that actually belongs to the surrounding class from the code related to the listener.
The actual contents of your listener implementation will affect the performance way more than the call to setOnClickListener. From the perspective of setOnClickListener, both calls are equal as they both pass an instance of a class implementing View.OnClickListener, whether reused or created.
Related
What is the proper way to call view's method:
findViewById(R.id.btn_Foo).setVisibility(View.GONE);
vs
Button fooBtn = (Button) findViewById(R.id.btn_Foo);
fooBtn.setVisibility(View.GONE);
As I understand correctly, as a general Java code efficiency rule, one should use variables. But in this case, what if the view method called only once - does it mean that calling setVisibility without defining a variable is more effcient?
does it mean that calling setVisibility without defining a variable is more effcient?
Performance-wise, the efficiency of the two approaches are almost, if not completely, the same, if that's what you mean by "efficient".
If "efficient" means the time it takes to write the code, then of course the first approach is more efficient.
But in this case, what if the view method called only once
As a general rule, when you want to use the foo button later in the code, you want to make it a variable. If you just want to use it once, it's fine to not declare a variable. However, not needing to use an object twice now does not mean you won't need to use it again next month. It is very possible that next month, you found a bug in your code or you want to add a new feature and now you need to use foo button twice. If you haven't declared fooButton as a variable a month ago, you would have to declare it now.
So unless you are 200% sure that foo button will never be used again in the same scope, make it a variable. It is a View after all, and you tend to refer Views very often.
I'm using a UI framework which doesn't follow a strict MVC design. I create a component and add the appropriated properties to "style" this instance of a class. Some pseudo code:
Button bu = new Button();
bu.setCaption("Something");
bu.addClickListener(...);
bu.setAnotherProperty(1);
However, when do I decide to make an extra class instead of this whole setter block?
Like (pseudo code):
public class MyButton extends Button {
this.setCaption("Something");
this.addClickListener(...);
this.setAnotherProperty(1);
}
Is it a good practice to do it like this always? Is it a bad practice to do it in general? Or is there a special case where one should decide to create a class instead of a huge setter block?
Your MyButton isn't really (at least based on the code shown) a special type of button. It's just a Button with some parameters set in a certain way. Based on that I would probably not create a separate class, but factory methods that build buttons according to different specifications.
This has the added benefit that if you suddenly realize that you need 2 types of "special" buttons, you'd add another factory method instead of creating another class that's still basically just a Button with some extra make-up.
So instead of Button b = new MyButton(); I'd have something along the lines of (implementation style free) Button b = ButtonFactory.myButton();.
Do you use your custom button more than once? If so, then it would be good practice to create a separate class. If not, then generally it is not necessary.
Even if this custom button is only used once, I'd still recommend a separate class for "safe keeping".
Scenario, I have two activities, activity A, and activity B, they both extend from Activity, I also have a base menu xml on my ActionBar has onClick defined on a handler() method, how do I go about making this method available for my two activities without implementing it in both?, is making a common activity SuperClass the only way?
The generic answer is that you could either make a common superclass, as you say, or you could create a helper class, where each Activity class that uses the method would have:
public void onSomethingClick(View target){
MyActionBarHelperMethods.onSomethingClick(View target, /* whatever other things from this class you need */);
}
This can get kind of verbose if you have a lot of things you want to handle this way, but it's less verbose than implementing the same method everywhere. It will also be painful to implement a new item in your action bar this way (since you'd have to add the method to every Activity you want to use it). However, once again, it's less painful than having to modify the method in every place if you want to change it.
One way to possibly mitigate the headache when you want to add a new method would be to make each Activity implement an interface that contains all of the action bar methods you want them to have; most IDEs will realize you've added a new interface member and offer to add it to all of the implementing classes.
I have been perusing the open source code of JMapViewer. If anyone else wishes to look at it, check the SVN.
In a nutshell, the main class is JMapViewer, which is an extension of a JPanel. There is another very important class called DefaultMapController which acts as a MouseListener for the main class.
The first weird thing I noticed is that the viewer has no references to the controller. The JMapViewer constructor instantiates an anonymous instance of the DefaultMapController, like this:
public JMapViewer() {
// other stuff
new DefaultMapController(this);
}
This seems to me to be a poor design choice, since the controller has tons of methods (options, toggles, etc - example shown below), which now can not be accessed at all, so what good are they?
public void setMovementMouseButton(int movementMouseButton) {
// changes which mouse button is used to move the map
}
The controller does have a reference to the viewer as shown in the first snippet above, which is how it is able to exercise control.
However, then I thought of something even weirder! If this anonymous instance of the listener has no references, why is it allowed to even survive? Shouldn't the GC destroy it quickly? Or is GC smart enough to know that a listener class which references a live JComponent must also stay alive to work properly, even if it has no name for some strange reason?
So, two real questions:
why does GC not destroy object?
is this indeed a poor design choice, or is there some way I'm unaware of to access the controller from the class which instantiates the viewer?
I want to contribute to this open source library, and my first idea for a change is to change the JMapViewer class to have a field referencing its controller, and to change the constructor to assign the currently anonymous controller to this new field. But, I want to make sure I'm not ignorantly missing something. I have searched the entire codebase for the text DefaultMapController, and it only occurs in its own class definitions, and in the anonymous instantiations in the JMapViewer constructors.
EDIT:
It does indeed appear that there is a way to access the anonymous listeners, by using the java.awt.Component method getMouseListeners(). So technically in my application I could search this collection for instances of DefaultMapController, and use that to access the methods I need to use to change the controller options.
To play devil's advocate though, if I go with original idea and give the map a reference of its controller, now I have a sort of circular reference (map knows of controller and controller knows of map). Is this a bad idea?
The abstract parent, JMapController, holds a reference to the JMapViewer passed there by the DefaultMapController constructor:
public DefaultMapController(JMapViewer map) {
super(map);
}
Addendum: The map reference held by the controller is used to (selectively) add up to three controller references to the map's EventListenerList, discussed here. Any one of these would preclude GC. At least one salutary design benefit is that a concrete JMapController need only implement available interfaces.
As suggested in this MVC outline, it would be unusual to give the view a reference to the controller. In contrast, there's nothing wrong with letting the controller register as a listener to the view, as suggested here.
Note that only the no-argument JMapViewer constructor installs a DefaultMapController. You can use the alternate constructor, as noted in comments at line 57-59 in revision 29113 of Demo.java. A complete example is examined here.
1) Everything you know is that, if and when the VM deems it to be appropriate, it will collect some or all of the dead objects. The GC is not required to do anything.
2) The best thing is to ask to the maintainer of the library. Anyway, as a general rule, I would not bother to change anything unless there's a good reason to, e.g. if it sensibly improves readability, and would rather focus myself on real problems.
3) Not sure if that's the case, but, when you serialize a JComponent, you also serialize all of its fields. And you do not want to serialize a lot of unused stuff.
I guess this is a lame question, I can't even make up a proper subject! Here is what I'm trying to do under Android:
public void onCreate(Bundle savedInstance) {
...
AskFilename ask = new AskFilename();
...
}
Here, AskFilename class will present a user interface to let the user enter a filename. However, the ask object will be out of scope once the onCreate() method returns. So this means there will be no reference to ask any more (assuming inside AskFilename class, I did not assign its this pointer to any other variable), and so GC will, sooner or later, "collect" it. When this happens, if the user hasn't OK'ed the dialog box, the code in AskFilename is already unavailable and therefore the system will crash. Is my understanding correct?
(I can't think of a way to experiement with this idea, because I don't know how to make GC do its job. It seems that GC kicks in only when it wants to! Is there a way to make it do its job?)
If the above is correct, then what is the proper way to new a UI-related object? I know I can make evrything inside AskFilename static, or I can make ask a static vairable and assign it to null when it's done. But is there any other way? Or, the idea itself is bad in the first place?
(Does it make any difference if AskFilename is an "inner" class of the Activity? Like MyActivite.AskFilename.)
Thank you in advance.
Firstly, you can just put the declaration AskFilename ask; outside of the method declaration, i.e. as a member of your class. Then you initialise it with ask = new AskFilename(); in your onCreate method.
However, the thing to know is that your constructor probably won't look like that. Every Android UI component contains a callback (a reference) to the thing containing it. You typically do this by passing a Context to the constructor of a UI component- inside an Activity, the context is usually just the Activity itself, so you just use the this keyword. e.g:
TextView tv = new TextView(this);
However you construct your AskFilename dialog, I expect you will need to pass the Context down to its components. So your constructor will probably need to take a Context argument:
ask = new AskFilename(this);
Additionally, your Activity will hold references (implicitly) to all of its UI components, and dialogs it shows with onCreateDialog() So your object won't get picked up by the GC.
It gets these references either when you call setContextView or make the dialog.