Why are lifecycle methods in activity class defined with protected access specifier - java

Why are the lifeCycle methods in android have access specifiers as protected ?
what i understand about Access-specifiers is as below::
But why should we need to make all the life-cycle methods as
protected
I notice this when i override the lifecycle methods
I know over-riding the methods of Activity class as methods in
Activity class are defined protected
But why are they defined as protected

They are protected for encapsulation within the framework package android.app and subclasses.
They are to be called by android.app.ActivityManager (same package) only. Depending on the method implementation, things could get messed up, if one can call those methods arbitrarily, from anywhere.
So, this is by design and that design helps to avoid certain conceptual errors.
If you really must have a public method, just implement one and use it from outside and within the corresponding lifecycle method.
However, though not recommended in this case, one could override protected methods with public methods.

i am defining here why public and protected and how it work:
It's useful to have public onClick methods because you can "force" certain buttons to be clicked programmatically. A common example of this is causing the same to code to execute when the user presses the enter key, or pressed the Submit button.
I don't think Android calls Activity.onCreate directly. Note that Activity inherits from Context (which does have a public constructor). It is my understanding that the constructor triggers some events to occur, and the onCreate/Pause/Resume/Destroy methods are called internally to the class at the appropriate time.
For example, when you create an activity, the view XML file has to be parsed and inflated. This happens automatically, so there's something happening behind the scenes that you don't directly control.

Not public because those lifecycle methods are essentially used internally by the SDK and are not meant to be called by any other classes (you are not supposed to call anywhere activity.onResume() from any class, this is done automatically).
Not private to allow some custom code to be ran by subclasses.

Related

Can I pass an interface to bundle of a Fragment?

Since Fragments need to survive configuration change, it is strongly suggested by Android that we should implement our own newInstance() method when creating a fragment, passing necessary data to its Bundle instead of using new MyFragment().
Now, the problem is, I want to pass a callback (interface) to this Fragment.
At first I tried to make my interface extends Serializable, and simply use args.putSerializable("myInterface", myInterface).
But when Android try to save its state (parcel it), an Exception is thrown (Parcelable encountered IOException writing serializable object).
I know the official way to do this is to make the caller Activity implements the callback, and reference the callback to the activity during onAttach() of the fragment.
Yes, it works, but it feels weird, because I am actually creating a library and now instead of asking user to pass a callback to the builder, I have to tell them your caller activity must implements a certain interface.
More importantly, what if I want to show this Fragment from another Fragment? onAttach() always attach to an Activity.
So, is there a way that I can let user pass the callback to the fragment, and being able to survive configuration change (e.g. device rotation)?
UPDATE
As requested, here is the interface that I want to pass:
public interface OnImageSelectedListener extends Serializable {
void onImageSelected (String uri);
}
And how I construct this interface:
new OnImageSelectedListener() {
#Override
public void onSingleImageSelected(String uri) {
Glide.with(MainActivity.this).load(uri).into(ivImage);
}
}
At last, I come to the conclusion:
We should not retain the callback.
Imagine the callback does the below code:
Glide.with(context).load(image).into(imageView);
When device rotates, the above imageView, which belongs to an activity or another fragment, is also destroyed and re-created. The old ImageView that is referenced in the retained callback no longer exists.
This will either make Glide throw an exception; or leaks the old ImageView and thus the whole Activity.
That's why we should always reference the callback to an attaching Activity.
And if the caller is a Fragment, instead of referencing the callback in onAttach(), simply reference the parent fragment in onCreateView():
if (getParentFragment() != null && getParentFragment() instanceof YourInterface) {
yourCallback = (YourInterface) getParentFragment();
}
So if to answer the original question,
Can I pass an interface to bundle of a Fragment?
The answer is, probably no, but you just shouldn't.
The reason you are facing this issue is because,
Glide is non Serializable data and you cannot serialize it. Since serialization is a process defined by Java and done on JVM, it doesn't understand Parcelable, hence fails with an error. This is also applicable even if you are just using them in the callback method.
But since you are developing a Library, you won't be able to control the usage of your Callback interface. So the solution would be avoid sending this object by Serializing it.
Instead, when usecase of your library starts (there must be some entry point to tigger the usecase), you need to request your to pass the reference directly to your method. You can then maintain the reference and execute callback when necessary. You need to implement some wrappers to achieve it. And communicate internally through LocalBroadcastReceiver
If the above approach is not possible, then only solution would be to ask user of your Library to register for LocalBroadcastReceive and deliver result through Broadcast.

Class visibilities and instantiation in MVP

I am hoping to use the MVP pattern in Android that I roughly came up with the following packages and classes:
Here are 3 packages:
com.myview
mainActivity //public
com.ipresenter
IPresenter //public
com.PresenterImpl
Presenter //protected
Presenter implements IPresenter.
What I intend to do is to make Presenter protected and can be instantiated only in mainActivity. Other words, I would like to limit its visibility and creation of this class can only be made possible through mainActivity class.
Since its constructor is implicitly declared as protected, I cannot instantiate Presenter within class mainActivity.
How could I do this without having to make Presenter public? How can I limit the visibility of a (or some) class within a package and allow its creation only through another class that lies within another package?
I thought about the classLoader Iterator method, but is this an overkill or it is not necessary because there are other ways / patterns?
Many books seem to suggest to limit the visibility of classes as much as we can, so I am taking this opportunity to learn and utilize good practice.
Addendum:
In addition to the aforementioned, my ultimate goal is to be able to declare the presenter within the mainActivity using the interface type. So, if in the future I had more than one presenters, they would all still be of the interface type IPresenter.

The processEvent() method of Component class

When handling various events, my general policy has been to create a xxxHandler class like MouseHandler, WindowHandler, etc which extends its appropriate xxxAdapter class provided by Java.
I was just going over some other text about handling events and it says that whenever you extend any EventListener interface, say ActionListener, you must call the enableEvents(AWTEvent e) method in the constructor and call the super.processXXXEvent() whenever an event is generated.
I find this approach highly confusing. These methods have the access specifier as protected so I assume that these are for internal use only ?
What exactly are those methods for ?
Are they really needed for handling events ?
Do they offer any benefits over the usual actionPerformed(), mouseMoved(), etc where you add your code to handle the events in the method definition without calling any super methods?
Help needed. Simple words are highly appreciated rather than technical mumbo-jumbo.
What exactly are those methods for?
The processEvent() method filters the types of events that comes to it. The parameter to this method is of type AWTEvent type.
After filtering, this method calls the corresponding processXYZEvent() method which takes the corresponding event object.
For example, processMouseEvent(MouseEvent)
The processXYZEvent() method notifies the corresponding listeners about the event by passing the event object to the handler.
For example, processMouseEvent(MouseEvent) notifies the registered mouse listener(s).
The enableEvents() method decides what event(s) to give to the processEvent() method. This method cannot be overrided since it is final. However this can be accessed in the sub class of the Component class to decide what type of events that the component support.
Are they really needed for handling events ?
Their role is mentioned above. This means that they are needed for handling events because you can only handle an event when an event object is created and dispatched and those methods do this.

Make java methods visible to only specific classes

I have a manager class that is responsible for managing Objects of a certain kind. To do so it needs to manipulate these Objects, but these Objects have no relation to the manager whatsoever, so design technically, they are in separate packages "project.managers" and "project.objects" . The important thing is that the Objects in question should only be manipulated by the managers and nowhere else, but need to be accessible by every other class in the project.
As such I'd like to have the managers have access to manipulating methods, but restrict access to every other class. The most obvious one would be to move the manager class and object class into the same package and declare manipulating methods protected, but as the managers and objects are completely separate entities they don't fit there philosophically.
(This is partly because I want my IDE to stop showing me the manipulating methods whenever I autocomplete code on the Objects in question so I always have to go the route through the manager so corresponding tables are correctly updated whenever I change the Objects in question).
Are there any ideas to that or is the obvious way the best in any case?
Why not have an interface called
ManagerFunctions
and another called
ClientFunctions
You managed objects will implement both of these.
When you create the managed objects, you pass them around, but only as references to ClientFunctions. The manager objects will, however, refer to them as ManagerFunctions and consequently have access to their 'managed' functions. The appropriate casting will simply expose the appropriate methods.
Your IDE will automatically present you wil the appropriate methods depending on how these objects are referenced.
You're asking for something akin to the "friend" declarations of C++, but there's no direct equivalent in Java - package visibility is the nearest. Alternatively you could go for a model like the XML DOM, where the methods that should be public are defined in interfaces and all client access is via these interfaces. The manager would know the concrete class of the implementation so could downcast to that as required.
As such I'd like to have the managers have access to manipulating methods, but restrict access to every other class. The most obvious one would be to move the manager class and object class into the same package and declare manipulating methods protected...
Technically, you would declare the manipulating methods package protected (no modifier at all). Protected methods allow the class to be extended easier.
but as the managers and objects are completly seperate entities they don't fit there philosophically.
I understand. Java doesn't have the "friend" declaration that C++ has.
You could comment the manipulating methods, but that doesn't solve your Eclipse problem.

Is there anything wrong with using a public static Context? ( Regarding getResources() )

Recently I ran into a problem when trying to load an bitmap outside of my main class. I found that within my main class I could pass this as a Context to any given function allowing me to call getResources() from within that function. There are a couple of things about this which don't make sense to me.
The keyword "this" simply refers to the current object the function is running in, right? If so, how can I pass my main class as a Context by using "this"? It doesn't even have a Context in it. I am using "extends Activity", but Activity doesn't seem to contain any function called getResources() in it either.
I found a workaround which allows me to do what I want a bit easier which is to declare a public static Context appContext; within my main class. Then, within onCreate() I set appContext = this; Then, from elsewhere I can call MainActivity.appContext.getResources() whenever I need it. So, I really have a few questions here.
Why are MainActivity(my main class) and appContext not essentially the same thing when appContext is set to "this" from inside MainActivity (There is no such thing as MainActivity.getResources())
Is this unsafe to do? Could this cause any potential problems in my program?
Is there a way to load images without having to use getResources()?
What is the proper way to show my code in this website? The standard I am used to ([code][/code] tags) don't seem to work properly in the preview, so I am assuming it is handled differently here. The formatting help page says to simply use four spaces, but that doesn't seem to show any difference in the preview section either.
EDIT:
I just read in another thread somebody said
now everything depends on your main activity's onCreate method having been called.
That got me thinking. Under what circumstances would onCreate not be called? It seems like if it wasn't called the program would stop working properly in many ways not related to having a static variable initialized inside it(ie. setContentView would not be called).
So assuming that there is nothing wrong with doing it this way, the only drawback I can find, is that "MainActivity.appContext.getResources()" is a lot to type to call a function. Is there any way to create a sort of alias for this? I suppose I could create a function which simply calls that, but that just seems silly.
If you look here you see that activity is a subclass of Context.
You can format code with a backtic, or just use the {} buttons on the editor. See the markdown manual for more info.

Categories