Can I call setHasOptionsMenu() from Fragment Constructor? - android

Calling setHasOptionsMenu(true) from constructor, which is obviously called even before onCreate(), works perfectly! Can I do that? What will be problems?

Check here fragment - Android
Applications should generally not implement a constructor. The first
place application code can run where the fragment is ready to be used
is in onAttach(Activity), the point where the fragment is actually
associated with its activity. Some applications may also want to
implement onInflate(Activity, AttributeSet, Bundle) to retrieve
attributes from a layout resource, though should take care here
because this happens for the fragment is attached to its activity.
You may want to use another lifecycle event for this.

Yes, you can call setHasOptionsMenu(true) from the constructor.

Related

lateinit property not initialized when Activity is re-created

In my Activity I have a lateinit property called controller that my Fragment uses.
This property is initialized in Activity.onCreate(). My Fragment gets its reference back to my Activity through onAttach(). The Fragment then calls myActivity.controller in Fragment.onCreate().
Normally controller is first initialized in Activity.onCreate(), and after that, the Fragment is added. So this works just fine.
But when my Activity has been killed, it tries to recreate itself and its fragments. This causes Fragment.onCreate() to be called before the initialization took place in Activity.onCreate().
These are the options I see right now:
initialize controller before super.onCreate() (if that's even possible)
move the call to myActivity.controller to a later lifecycle callback, as onViewCreated()
something with ::controller.isInitialized available in Kotlin 1.2
What is my best option here?
By reviewing the Fragment lifecycle, in fact the safest point to do it will be #onActivityCreated(android.os.Bundle).
Even when #onAttach() looks like it is called when the Fragment is attached to the Activity, I'm not sure if this is completely guaranteed, as the old #onAttach(android.app.Activity) is deprecated, and the new #onAttach(android.content.Context) is recommended.
The best way to handle such scenario where an object is used before initialization is by checking with isInitialized() property and then using it.

Why does this make my app crash and what's the appropriate solution?

I have a button that I want to change its value often, so my Activity has a private variable :
private Button p1_button = (Button)findViewById(R.id.firstbut);
This simple line makes my app crash. If I put inside the onCreate it works and I can interact with the button (change text etc).
EDIT : I think I found the reason. I should initialize AFTER setcontentview ?
EDIT: Thank you for the constructive answers. I have now a different problem I removed the initialization and I did it on onCreate and it works (But I keeped the p1_button declaration as a private field). But when I tried to modify the button in a different method of my activity (just changing the text), it crashes again. So the return value of findViewById is "local" to the method where it is called and I should setcontentview in every method that access UI elements ?
Do not call findViewById() until after you call setContentView(). Otherwise, the widget will not exist.
More generally, do not call inherited methods on Activity until after super.onCreate(), unless specifically advised to do so.
It depends where you are calling this line.
http://i.stack.imgur.com/6EQaU.png
The onCreate() method contains a call to setContentView() and before this is called, Android has no idea what to do with your button as it hasn't been inflated yet!
Therefore as a really easy rule of thumb, always make sure setContentView (or if you're dealing with fragments onCreateView()) have been called and completed. Only then will findViewById() work.
If you would like further guidance, please post some code in which the crash occurs.
edit: I tried to add the image properly but don't have enough rep.
To understand this you need to know the Activity lifecycle. You are trying to look a view which has not yet been created by Android.
As per the android lifecycle explained here "http://developer.android.com/training/basics/activity-lifecycle/starting.html". In onCreate() method the activity is created and you can access different views of the activity. If you will try to look for view before onCreate() the app will crash as it does not know whether that view exists or not.

Click Events inside fragment

I have a dashboard that is a fragment. Everytime I click a button, the dashboard is replaced by another fragment.
The click listener is implemented inside the dashboard fragment class. But I read somewhere that the better way to do it is to make the listeners inside the activity. Is it true? Why?
If yes, I can change it, i only have to copy the method in dashboard fragment to the activity, and make use of XML onClick feature.
I honestly can't think of a reason for declaring an onClick listener for a fragment in the activity.
First, fragments are suppose to be modular. Maybe you use it with this activity or that one. Putting the onClicks in the activity hardcodes a relationship between the two. Your activity is searching for the fragment, which isn't always there, and your fragment can't work except in that activity.
Second, where you declare your on click determines where it's implicit reference will be to. If you declare it in the activity, it can call activity functions, but It has no idea which fragment it came from. How does it reference fragment functions / data? Sure there's elaborate workarounds but why?
On the other hand, if you put it in the fragment, it can call the fragment functions. and it has the same life-cycle as the fragment (being attached to a fragment view), so the implicit reference isn't going to create a memory leak (by itself anyways). And if you want to call the activity, just use getActivity and cast it to your interface or subclass.

Best practice to initialize values in views after OnCreate

I have some problems initializing some values for some views in my Android Activities cause for me to be able to get the views I have to wait for the activity layout aswell as the fragment layout to be inflated until I can initialize the views values. I know i can initialize the views in the fragments OnCreateView but I would like to avoid that and instead have some kind of method that is run right after the onCreates/onCreateView's are done.
Is this possible if so how? And what is the best practice of modifying/initializing views?
Thanks in advance
Unless you have a special case you should not deviate from the lifecycle of a Fragment or Activity.
Anyway if so, Calling a method as you asked for, look at the MainActivity class on this example. It uses a Handler to do work on the UI Thread
You could do this in the onStart() or onResume() methods, which are called after onCreate(), but also after stopping or pausing of the Activity.
For more detailed Information have a look at the Activity Documentation
You should also try to work on the formatting of your question, I'm not sure whether I understand the problem correctly, or not.
You can use the way mentioned over here. It's cleaner.
you put the following method in the fragment.
public void initFragment() { //Do your required things here }
After creating the object for the fragment (for instance example given below)
mFragmentManager = getSupportFragmentManager();
mIssDetailsListFragment = (IssDetailsListFragment) mFragmentManager
.findFragmentById(R.id.fragment_outlet_list);
you call the method initFragment() (Sample code given below)
mIssDetailsListFragment.initFragment()

To use getSherlockActivity() or getActivity() or other?

I have an Android app with TabManager. Due to change of Android API, I need to upgrade my app for Activity to contain the Fragment. To provide backward compatibility, I use ActionBarSherlock.
My App is working fine. However, looking at the Google Play Developer Console, there is always few crash reports on "java.lang.NullPointerException" on the line with getSherlockActivity(), I think only less than 0.1% out of total users are affected.
For example,
// Example 1
File file = new File(getSherlockActivity().getCacheDir(), "filename");
// Example 2
getSherlockActivity().setSupportProgressBarIndeterminateVisibility(false);
My question:
1. Should I change all the getSherlockActivity() to getActivity()? Or under certain rule, it is mandatory to use one of them?
2. What is the difference between them?
Thanks a lot.
The only difference is that with getSherlockActivity () you get the result of getActivity() but casted as a SherlockActivity. This allows to get access to the ABS specific apis.
If you just need something that is general enough to be in the Activity class, just use getActivity(). It will highlight this, otherwise highlight the fact that you use something that is ABS specific using getSherlockActivity ().
The NPE can come from :
using getActivity() (or siblings...) before onAttach has been executed
using getActivity() (or siblings...) after onDetach has been executed
So the solution is to check if your fragment is attached before using its activity :
if( isAttached() ) {
getActivity()....
}
Same topic
The NullPointerException is normally
Caution: If you need a Context object within your Fragment, you can call getActivity(). However, be careful to call getActivity() only when the fragment is attached to an activity. When the fragment is not yet attached, or was detached during the end of its lifecycle, getActivity() will return null.
This exception probably means that the code is being exectuted when the fragment is not attached to an activity.
The reference returned by getSherlockActivity() is set when the Fragment is attached, and then cleared (set to null) when the Fragment is detached. If your code tries to reference getSherlockActivity() before or after this, you would get a null-pointer.
getSherlockActivity is just a shortcut to:
(SherlockActivity) getActivity()
So in your case there is no problem to use getActivity() instead in Example 1 but in Example 2 it will not work since it is a method of SherlockActivity.

Categories

Resources