NullPointerException when trying to access views from a Fragment - java

I basically want to change the visibility of some xml elements in my fragment when the "onRewardedVideoAdRewarded" method in my MainActivity gets called.
Here is the onRewardedVideoAdRewarded method in my MainActivity.java:
#Override
public void onRewardedVideoAdRewarded(Placement placement) {
MyFragment myFragment = new MyFragment();
myFragment.rewardedVideoFinished();
}
and here is the "rewardedVideoFinished" method of my Fragment:
public void rewardedVideoFinished (){
myButton.setVisibility(View.INVISIBLE);
...
}
I'm initializing the button in my fragment's onCreateView method like this:
final View rootView = inflater.inflate(R.layout.tablayout_rewarded,container,false);
myButton = rootView.findViewById(R.id.mybutton);
When the Rewarded Video Ad finishes and the "onRewardedVideoAdRewarded" gets called, the app crashes with the following message:
"java.lang.NullPointerException: Attempt to invoke virtual method
'void android.widget.Button.setVisibility(int)' on a null object
reference"
I know what NullPointerExceptions are and I know that "myButton" is not initialized when I call it, but why is this the case? I thought with making a new instance of my Fragment it gets initialized.
How can I fix the problem and make the view in my fragment invisible when the rewarded video ad finishes?
Thanks.

Related

Initialised ImageButton in other Activity throws nullPointerException when referenced in MainActivity

I'm very new to Android and Java coding in general, so bear with me if I don't understand basic concepts.. This is just a test to see if something works, so It might not initially make any sense.
I have two activities, Main and Other.
the Other Activity has an imageButton with visibility initially set to invisible.
When MainActivity is created, it should look for that imageButton in the Other activity, and set it's view to visible.
Though when debugging, all I get is a nullPointerException, because the button has null as value. How can I make it reference the button?
Part of Main Activity:
public class MainActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pstep();
}
public void pstep() {
int pstep = 0;
ImageButton panfav = (ImageButton) findViewById(R.id.favpancake);
panfav.setVisibility(View.VISIBLE);
}
Part of Other Activity:
public class navfav extends AppCompatActivity {
ImageButton panfav = (ImageButton) findViewById(R.id.favpancake);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navfav);
}
public void fab(View v){
ImageButton panfav = (ImageButton) findViewById(R.id.favpancake);
panfav.setVisibility(View.VISIBLE);
}
XML linked to Other Activity:
<ImageButton
android:id="#+id/favpancake"
android:layout_width="wrap_content"
android:layout_height="137dp"
android:layout_alignParentStart="true"
android:layout_below="#+id/imageView3"
android:background="#android:color/background_dark"
android:contentDescription="#string/nav_cook_dish"
android:onClick="fab"
android:scaleType="centerCrop"
android:src="#drawable/dishpancake"
android:visibility="invisible" />
Log:
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.widget.ImageButton.setVisibility(int)' on a null object reference
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method
'void android.widget.ImageButton.setVisibility(int)' on a null object reference
at com.p2.rookie.MainActivity.pstep(MainActivity.java:23)
at com.p2.rookie.MainActivity.onCreate(MainActivity.java:16)
Shoot if I'm missing anything you need to use, I'll provide as much as i can :)
Best
The visibility of the buttons are always "VISIBLE", please give me the log
and in the navFav activity the "fab" method are not in the onCreate
you are getting nullPointerException because ImageButton with id favpancake is not present in MainActivity layout activity_main
public class navfav extends AppCompatActivity {
public static List<String> recipes;
// other code here
}
and then when you want to add recipe to shown in Other Activity listView,
recipes = new ArrayList<String>();
recipes.add(recipe);
Now when you open the other Activity all those recipes will be available in list name "recipes". which you can use to show in your listView.
One Activity can and should not reference elements in other Activities.
If you call 'setContentView' with a layout file, you can only reference the views in that layout file.
Try and tell us what you're trying to achieve and we might be able to help you out in improving your code.
(Posted on behalf of the OP).
Just read a bunch of other stuff elsewhere, and I think something made sense now! Instead of creating new intents and startActivity'ies when changing layout/pages, I just setContentView to new layouts/pages, and gather all methods from different activities in one activity - That's how basic this fail was I think? ;)
Then all views and methods can reference each other.

Accessing adapter inside Fragment

I have a main Activity.class that runs a Fragment (not FragmentActivity) via ViewPager. And I have a custom adapter with recyclerview list inside the fragment. There is an issue with accessing adapter outside and inside the Fragment. So:
This code fully works:
private List<MyQuestionList> theList;
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
recyclerView = (RecyclerView) theview.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
theList = new ArrayList<>();
requestQueue = Volley.newRequestQueue(getContext());
adapter = new MyQuestionsAdapter(theList, getContext());
recyclerView.setAdapter(adapter);
updateAdapter(); // <-- ATTENTION PLEASE, I'VE CALLED THE FUNCTION INSIDE THE FRAGMENT
}
public void updateAdapter(){ // <-- METHOD IS PUBLIC
removeItem(0);
}
***** And there is located parser's method where items are fetching from server
and adding to recyclerview via adapter successfully.
But the code is too long, and anyway there is nothing interesting :) *****
private void removeItem(int item){
theList.remove(item);
adapter.notifyDataSetChanged();
}
But when I call the same method (updateAdapter) from main Activity.class like this (not inside the fragment on run):
Fragment_Questions frau = new Fragment_Questions();
frau.updateAdapter();
code doesn't work. Here is log:
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.List.remove(int)' on a null object reference
Since you said that a Fragment_Questions is already added to a ViewPager, use the reference of the added Fragment_Questions object to call updateAdapter().
In the code given below, you are just creating an object but never adding it to a viewpager. Hence, the onCreateView method is never being called, which leads to the NullPointerException.

Fragment lifecycle method sequence

I have attached a fragment at runtime in Activity's onCreate() method. I am trying to understand the sequence of lifecycle method calls on the fragment. However the behavior seems to be inconsistent from what is expected. I am doing a screen rotation to understand this. The below is the log after screen is rotated. Have put the marker in the log at the point of doubt.
Can someone explain what is happening here?
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(tag, "OnCreate()");
if (savedInstanceState != null) {
Log.d(tag, "SaveInstanceState is NOT NULL");
}
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
mainFragment = new MainFragment();
fm.beginTransaction().add(R.id.fragment_container, mainFragment, "MainFragment").commit();
}
MainFragment﹕ OnDestroy
MainFragment﹕ OnDetach
MainActivity﹕ OnDestroy
MainFragment﹕ onAttach() <<< Getting called before Activity's onCreate()
MainActivity﹕ OnCreate()
MainActivity﹕ SaveInstanceState is NOT NULL
MainFragment﹕ onCreateView()
MainFragment﹕ SaveInstanceState is NOT NULL
MainFragment﹕ onAttach() <<<<<< onAttach() on Fragment called again
MainFragment﹕ onCreateView() <<<<<<< onCreateView() on Fragment again.
Below is the Fragment lifecycle:
As per your question, when the screen is rotated, it means that the fragment and activities need to be reloaded or "recreated". If you follow the lifecycle image, you will see that Fragment is first destroyed (because it was rotated), then detached. The activity gets detached next.
Then the fragment is attached (the fragment is the object that is called before the Activity). Thereafter the activity is created.
Read up on the Android docs for a better understanding, but above answers your doubts.

Update ActionBar title after leaving fragment

When my MainActivity is launched my ActionBar shows the app title. Once you navigate to a fragment through the nav drawer, the title is changed to match the fragment... however, once you navigate back using the back button, the title is left untouched and still has the title of the fragment. I am looking to change it back to the application Title.
I have tried to use the onResume() method in the MainActivity.java but it appears that does not get called once you leave a fragment.
#Override
public void onResume() {
super.onResume();
// Set title
getActionBar().setTitle("FuelR");
invalidateOptionsMenu();
}
Does anyone know what the best way would be to change the title back to the app_name ?
Thanks
Indeed destroying a Fragment within an Activity doesn't mean the activity will call onResume, first you have to notice that the Fragment lives within the Activity life context, and the Fragment do not alter it's life cycle, is just part of it, what you could do is within the fragment get a reference to the activity and set the title back to previous state, as shown below:
//In Fragment
#Override
public void onDestroyView() {
super.onDestroyView();
((Cast If Necessary)getActivity()).getActionBar().setTitle("Previous Title");
}
Or a more OOP approach would be, creating an interface that declares a method setTitlePreviousText, you implement that interface in your Activity class and from the fragment you could do this:
//In Fragment
#Override
public void onDestroyView() {
super.onDestroyView();
Activity act = getActivity()
if(act instanceof SetPreviousTextInterface){
//setTitlePreviousText will be called giving you the chance to just change it back...
((SetPreviousTextInterface)act).setTitlePreviousText();
}
}
This would be the interface file:
public interface SetPreviousTextInterface{
public void setTitlePreviousText();
}
Regards!

Get the Fragment View using findFragmentByTag dont return whit getView

Im try getView from my fragment instantiated using getFragmentManager.findFragmentbyTag, see my code below:
MyTaskFragment.java:
Initializing my Fragment
DialogFragment newFragment = new newTaskFragment();
newFragment.show(getFragmentManager(), "newTask");
inside MyTaskFragment have the DialogFragment basically this:
public static class newTaskFragment extends DialogFragment {
// ..
builder.setView(inflater.inflate(R.layout.new_task_dialog, null))
// ..
return builder.create();
// ..
}
and also inside MyTaskFragment jave a picker:
public static class TimePickerFragment extends DialogFragment
implements TimePickerDialog.OnTimeSetListener {
and this is the problem(inside picker):
Fragment fragment = getFragmentManager().findFragmentByTag("newTask");
View viewv = fragment.getView();
Button button = (Button) viewv.findViewById(R.id.choice_hour);
the Button above always returns null with error, the id is inside the layout R.layout.new_task_dialog. I don't understood.
Please someone helps me.
You may be receiving this error if:
Your View ID choice_hour has a typo and does not match the View ID
you expect to find in the View hierarchy.
There is more than one Fragment with the "newTask" ID which doesn't
share the same layout.
Your OnTimeSetListener is being called before your Fragment's
onFinishInflate().
Your OnTimeSetListener is being called before your Fragment's
onCreateView() is called.
Your OnTimeSetListener is being called before your Fragment is
attached to your Activity.
See this answer for more details: findViewByID returns null

Categories