Why not
AlertDialogBuilder builder = new AlertDialogBuilder(this);
builder.setTitle("foo");
instead of
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("foo");
Update: I want to know the reason behind this kind of writing/organization
According to the Javadocs, nested classes (and in this case, static nested classes) are generally used for three things:
Logically grouping classes which will only ever be used together.
Increasing encapsulation.
Increasing readability and maintainability of code.
Point #3 is one reason a lot of developers use static nested classes. Let's take, for example, the ViewHolder pattern in Android development. In a ListAdapter, we can make caching of lists easy by managing the contents of each list element in a ViewHolder (or similarly named inner class). In this situation, it is easy to notice that this specific ViewHolder is only for this class, and when we change this one, we don't change every single one. This means we don't need a List1ViewHolder, List2ViewHolder, ..., ListNViewHolder. Each List-type element can have its own ViewHolder.
Point #2 is a bit less relevant to this point, because we're dealing with static inner classes (that's what Builder is). But in this case, it prevents elements of the inner class from being accessed by the outer class.
Point #1 is the big one here, which is why I've saved it for last. Think of the situations in which you will use AlertDialog.Builder. I can guarantee, with 100% certainty, that every single time you use AlertDialog.Builder, it will be in the building/creation/handling of an AlertDialog. Consequently, this means that every use of AlertDialog.Builder is tied to how AlertDialog works. (This ties in somewhat with point #3; it's easier to maintain two classes in one file than to have them separated.)
Similar to points #1 and #3, but also of its own rite, is the fact that by keeping Builder within AlertDialog, we are not polluting the android.app package namespace. We still keep just AlertDialog within it; but Builder hides within that.
Android is not the only system that does this; the MotiveWave SDK does this also, as do the Adobe Access and eBay SDKs (which I lack links for). I also believe Java EE uses this methodology as well. You will also see it often in Enum types, which in turn is because of the reasons covered in point #1.
Now, you asked why we use AlertDialog.Builder instead of new AlertDialog(), and build it from the object instead of from the builder. The answer here is the same as the factory method pattern seen commonly in Java and other object-oriented programming languages. Notably (from Wikipedia), there are three reasons for this:
The creation of an object precludes its reuse without significant duplication of code.
The creation of an object requires access to information or resources that should not be contained within the composing class.
The lifetime management of the generated objects must be centralized to ensure a consistent behavior within the application.
These explain themselves pretty well; they speak against code duplication (being able to handle all creation functionality within one class), unauthorized access (bad encapsulation practices), and consistent behavior of construction. Also unlisted here is code readability.
I suspect--on a hunch--that AlertDialog is a very resource-intense process. It halts parts of the OS, keeps others running, has to load system resources, and so on. As this answer details, we do not want to provide direct access to the outer class (AlertDialog in this case). This allows the Builder to handle all resource-intensive operations properly. It also keeps us from having to handle esoteric situations which the OS developers considered, but we did not.
So, to conclude, this is actually a decently common design pattern, but not one that has a real explicitly defined meaning. Rather, it is for ease of use, understanding, and maintainability. You mention a concern about design considerations above; I wouldn't worry too much on that. Just keep in mind that static inner classes should always be solely related to their outer class, and you should be fine.
Builder is the static inner class inside the AlertDialog class. So to create a Builder class object, you need to call AlertDialog.Builder.
As there is no class like AlertDialogBuilder so you cannot do that.
If you want you can also use as like bellow.
Builder builder = new Builder(this);
builder.setTitle("foo");
But to use like this you need to import the Builder class to your class like
import android.app.AlertDialog.Builder;
instead of just
import android.app.AlertDialog;
A simple example
class A{
static class B{}
}
you cannot use
AB obj = new AB();
you have to use
A.B obj = new A.B();
Hope you are clear now.
I'll try and clear you up behind this kind of organization.
First of all, Builder is a class inside the AlertDialog class.
Why would you create a class inside another class? I personally only create nested classes if I want to add more functionality to an existing class and don't believe that from a designing point of view that the class should be extended. I'm sure one could argue about this one, since there are tons of different ways to add more functionality to a class; yet nested classes can be preferred above others (for some people).
Here's oracles point of view on nested classes.
I'd only use nested classes if I find that it makes the code more maintainable and intuitive.
In this case I believe the guys over at Google found that instead of creating a new class called AlertDialogBuilder compared to AlertDialog.Builder, is because both yield the same results; a dialog displaying some information on the screen with some buttons. The only difference between both (I think) is that you can set positive, neutral and negative button on the AlertDialog.Builder (which gives more functionality to the class, yet not necessary more that the class should be extended, again personal opinion).
In the end what matters is that the code works (hopefully without any bugs), is maintainable, readable and intuitive. There's no definite answer to your question, since people have different opinions on this topic.
I hope this helps.
The approach used to construct AlertDialog Object is called Builder Pattern to enhance readability. When you want to construct a new object but this object requires a lot of properties to create it like too many parameters (more than 4) passing to constructor you will got confused . If you want to know more about builder pattern I think this answer will satisfy your needs. AlertDialog construction is quite similar to the example in the link :
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setMessage("Do you really want to exit?")
.setCancelable(false)
.setNegativeButton("No",
new DaialogInterface.onClickListener() {
public void onClick(DialogInterface dialog,
int id) {
((AlertDialogActivity) getActivity())
.continueShutdown(false);
}
})
.setPositibeButton("Yes",
new DialogInterface.onClickListener()) {
public void onClick(
final DialogInterface dialog, int id) {
((AlertDialogActivity) getActivity())
.continueShutdown(true);
}
}).onCreate();
}
This method return Dialog object that asks user if he/she wants to exit the application as you can see it doesn't make any sense to create an AlertDialog object by calling a constructor with too many arguments. Imagine if AlertDialog has such a constructor :
AlertDialog ad = new AlertDialog(getActivity(), "Do you really want to exit?",
false, "No", .... )//and the list goes on
Compare this approach with onCreateDialog method I think onCreateDialog method wins right ?
Related
I am trying to implement MVP architecture using google sample code for mvp. I have an activity as View that has a presenter and model. On button click user can capture and save image in external storage. And on capture click, I also need to play a sound.
I am not sure which code should be put in which class because I cannot put camera capture and play sound code in Activity (which I treat as view) to keep the view as dumb as possible and I cannot put that code in Presenter because it uses Android framework classes (context etc).
So, the only option is to put it in model but in sample code, model only has Repositories (that I believe is relevant to data sources only local/remote).
How to put this code in model and how to link it with other components like View and Presenter? Any guidelines?
Here's one way you can go about solving an issue like that.
Your problem is that some code makes sense to go into a presenter, however it's too Androidy, so you can simply interface around it.
What you basically need is two things that can do certain functions.
interface CapturingSoundPlayer {
void playSound();
}
interface ImageCapturer {
void captureImage();
}
Please note that names and method signatures are up to you and what you need, I am merely using them to make a point.
Now it's perfectly safe for your application to have those two interfaces as dependencies, they have nothing to do with Android, we have simply take then technology out of the equation and only left the behaviour.
You need to pass these dependencies to your presenter and use them whenever needed.
class Presenter {
private final CapturingSoundPlayer soundPlayer;
private final ImageCapturer capturer;
Presenter(CapturingSoundPlayer soundPlayer, ImageCapturer capturer) {
this.soundPlayer = soundPlayer;
this.capturer = capturer;
}
void onCaptureButtonClicked() {
soundPlayer.playSound();
capturer.captureImage();
}
}
Now the implementation for those interfaces can be completely separate from your Activity, making your view still stupid.
Those interfaces (and their implementation) are simply logical units/entities that your presenter uses to split up the logic. I simply think of the functions of "capture" and "playSound" as simple actions, just like view.showLoading, and your presenter plays an orchestrator, it uses "something" to manipulate the view, which is the view interface, and it uses something else to manipulate sound, which is the interface for doing that.
if repositories are considered to be data sources, then in my opinion those helpers don't fit under that definition.
If you have a utility to retrieve the images that has been captured, that would basically can be considered as a repo for your images, but simply taking an image, is just another action.
You can structure/organise them as you feel fit, but just because you are using MVP, not every class you create has to be either one of those letters (M/V/P).
Sometimes any of those layers will need classes that logical units to do something, so that you have better separation of concerns.
Consider you have quite complex formatting logic, it would make sense to separate that in a separate class other than the presenter, but does that mean that the separate class is now model? It could, but it doesn't have to be.
I have a method that darkens a given hex color and percent. Currently, the only place I use this method is within one of my Activity classes (I may or may not end up using it in other classes later on).
public static int darkenColor(int color, int percent) { ... }
However, where should I put this method? Should I create a new class called Helpers that contains all of these methods that I may use only once throughout the entire app?
This is just a matter of choice. You can have Set of utility classes and have these helper methods to be in those classes. But, This method is for not used in one of your activity, and If you do not see that it will get reused in the near future in some other point, Put it as a private method inside your Activity. I say this because you do not want to over complicate the code and also By this way another developer can easily follow the flow of execution.
But after sometimes if you feel, that this code is getting reused, put that into a logically meaningful Utility class. When the code base is huge, you do not have any choice to follow a solid standardization of there to put your code, That is why there are things like Layered architectures etc.
I've been working on android for few months, during my spare time, so probably i'm going to ask stupid questions.
In a class, I create an object, for example a button, and I'd like to 'reach' it from others classes.
Of course i could do it this way:
public class CreateButton{
public void createButton(){
Button myButton = new Button(context);
//I can "pass" my object to another class this way
ManageButton manageButton = new ManageButton(myButton);
// or this way
manageButton.writeButtonTextMethod(myButton);
}
}
or this way
public class CreateButton{
public Button createButton(){
Button myButton = new Button(context);
return myButton;
}
}
public class ManageButton{
public void writeButtonTextMethod(){
CreateButton createButton = new CreateButton()
Button myButton = createButton.createButton();
myButton.setText("W");
}
}
I'm wondering if there's a way to 'reach' myButton, created in createButton.class directly from ManageButton.class (and other classes).
With the code above, I have to 'call' createButton.class from ManageButton.class or vice versa to be allowed to manage myButton.
I can do it making myButton static, but it's not correct make view static.
For example, i can easily reach variables created in a class that extends Application. Is there something similar for views?
Much people/guides/articles claim is possible and correct sharing objects (and fields) between activities by using Application, this way:
Such people are idiots, as myButton will introduce a memory leak unless this is done very carefully.
So, I'm still not sure how i should share objects (TextView, Button, ImgaeView etc.) among different activities.
You don't share widgets between activities. At most, you share model data between activities (or, better yet, pointers to centrally-stored model data).
In a Web app, you do not share DOM nodes between Web pages, as that is not possible. At most, you share data passed as GET parameters and the like between Web pages, or you store data in local central storage (cookies, local storage, IndexedDB, etc.). Android activities are like Web pages -- they are loosely coupled.
If you have pieces of your UI that are so tightly coupled that they absolutely need to share widgets, they should not be separate activities.
Views are not meant to be shared across Activities. Even if you do disregard this and share them, you're more than likely to run into a WindowManager$BadTokenException, which essentially means you can't alter Views outside of its parent Activity.
However, to answer your question in a more general way about sharing non-view objects, the Application class is the right way to go. However, making the objects static is not the right way to do. Instead, make them instance variables, and access them in in your various activities by using:
Application application:
//Below line is in onCreate()
application = this.getApplication();
After that, simple access it using
application.myObject; //Or you could use getters and setters. Your choice.
Not quite sure why would u like to share one button between two activities?!
It is either button in ActivityA or ActivityB? No need, or use to do it..You shouldn't do it.
EDIT: This is more Java Basics topic then Android.. And from what I understood, u call "class" something that IMHO is method (because u can't CALL the class and because what did you described).
Best advices I can give u here:
Study Java basics (methods, classes, objects, constructors, inheritance..),
Study Android basics (simple examples with 1 activity til u understand it good),
Make MyButton Class which will extend standard button,
Create button(s) and change their properties
This few tasks will make u busy for some time. Take it easy because it will be easier later with complicated apps. Hope I helped you. Cheers
EDIT2: In last example u wrote (in comments to this answer), nothing make sense because as we wrote u before u don't share button between two activities. Pause! Read it again: You should't share button between two Activies. Questions u asked are not clear because for A and Z u can't say just class and "share" button between them. Which class? no line of code written so it is really difficult to figure out what u want.. :s
LAST LAST EDIT: Man.. Please understand that u r missing basics of Java. No bad intentions here, just try to guide u and tell u exactly what u should study. Why? Because it doesn't surprise me that you are confused to explain what u mean when classes are with one method named exactly the same.. They are just objects "doing something", u want to "manage" them by adding variable in constructor which doesn't exist etc.. Learn, next time write immediately code to save time for all of us. Cheers and enjoy learning
OOTB, Robolectric does not support Locales that well. Therefore, if your app is dependent on locales (which a lot of apps are if they are i18n'nd properly) this can be a royal pain. Long story short, I created my own ShadowFooGeocoder and ShadowFooAddress that allow me to simulate the locale I want. They're basically re-implementations of the existing shadows.
However, when I bind my class as such: bindShadowClass(ShadowFooGeocoder.class), this works great. At runtime, the correct shadow is returned. The problem is that I want to set up the simulations on this object and I'm not sure how. shadowOf(instance) where instance is an injected GeoCoder returns ShadowGeoCoder. I've tried working directly with the ShadowWrangler, but that also returns a ShadowGeocoder.
How can I get at my shadowed class that I've bound through the bindShadowClass(...) call so I can set my expectations (simulations)?
Note: This is a repost of the same question on the Robolectric group here. I posted here because my success rate of getting anyone to answer questions on the group is fairly low. I'm hoping for a better result here.
What I've basically done here is extend ShadowGeocoder like this:
#SuppressWarnings({"UnusedDeclaration"})
#Implements(Geocoder.class)
public class ShadowFooBarGeocoder extends ShadowGeocoder {
// implementation stuff
}
Then I would bind it using the bindShadowClasss(...) and when I retreive the shadow via the static shadowOf(...) call I get back a "ShadowGeocoder" which is an instance of ShadowFooBarGeocoder. I then cast it to that type and perform whatever work I need to.
I have a view that displays all the levels of my game. These levels are read by the activity and then passed into the view. I could read them from the view, but it's not really its responsibility, and I'm a fan of separation of concerns.
Right now, I'm calling a setter for this:
((GameView) findViewById(R.id.game)).setLevels(loadLevels());
However, I don't like the fact that the view will be dysfunctional if I forget to call the setter. Is there a better way to pass the levels in?
It is also a bit a matter of preference. Theoretically it's perfectly fine to pass the levels as you're doing. Alternatively, if you need more than just set the levels, but provide further functionalities (i.e. also saving of levels) I normally use a separate class responsible for handling such things (i.e. a Repository, some "Manager" class etc...). This class is then passed into the View on the constructor preferably s.t. one is forced to provide it. Of course, in order to separate things, I use interfaces rather than specific implementations s.t. it may then look as follows:
public class MyView {
public MyView(ILevelLoader levelLoader){
this.levelLoader = levelLoader;
}
...
}
Often, this may not work, because the view is something instantiated by the framework directly rather than by the application. In such a situation you're forced to do it through an appropriate setter. It is some sort of MVC/MVP pattern.
Just for your interest, you might also want to take a look at IoC containers and dependency injection. Guice provided by Google is a nice framework I've already used on Android.
I hope I didn't miss the point, but here goes:
Generally you have either a function setting something (like the text for a textview), or an attribute you set in the xml.
Take a look over at this answer I got on a question: How to layout a 'grid' of images in the center of the screen
There are some things the custom view needs, but lets take an example: 'numColumns'.
you can set it using setNumColumns (that would be the equivalent of your loadLevels() ? )
you can ignore it, it'll revert to default.
you can set it as an attribute lik so: app:numColumns="3"
You can try to use the attribute or the default in the class to accomplish this.
Make your view an abstract class with an abstract method getLevels()? This way, when you instantiate the class if you forget to pass the levels in your code won't compile.
Whether or not this is better is a matter of taste I guess :)