Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
So, the issue is this line
private static OnEntryClickListener mOnEntryClickListener;
Since it is static you have a single instance of the class at runtime. When you click on an item, a second instance of the same Activity is created, and another instance of mOnEntryClickListener
is created too, overwriting the previous one. So, when you press back to return to the first instance of the Activity, you are using the instance of mOnEntryClickListener
of the second Activity, that has been destroyed.
Farbod Salamat-Zadeh
Updated on July 09, 2022Comments
-
Farbod Salamat-Zadeh almost 2 years
I have an
Activity
, which itself has threeFragment
s.In one of these fragments, there is a
RecyclerView
with a custom adapter, and clicking on one of its items would go to another page, which is a new instance of the sameActivity
. However, a certain behaviour causes an error in my app.From my Activity, clicking on one of the items brings up the new instance of the same Activity, which is fine. Then I press the back button and I am taken back to the first Activity. But clicking on one of these items again (to launch a new instance of the same Activity) causes the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
It is also important to consider that I am calling the new instance of the Activity (i.e. where the three items are), in one of the fragments I have in my Activity. So, when I am calling it, I have something like:
public class MyActivity extends AppCompatActivity { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... ViewPager viewPager = (ViewPager) findViewById(R.id.detail_viewpager); viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager())); TabLayout tabLayout = (TabLayout) findViewById(R.id.detail_tabs); tabLayout.setTabTextColors( ContextCompat.getColor(this, R.color.text_white_secondary), ContextCompat.getColor(this, R.color.text_white)); tabLayout.setSelectedTabIndicatorColor(ContextCompat.getColor(this, R.color.white)); tabLayout.setupWithViewPager(viewPager); viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); } ... public class ViewPagerAdapter extends FragmentPagerAdapter { public ViewPagerAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { return 3; } @Override public Fragment getItem(int position) { switch (position) { case 0: return new MainFragment(); case 1: return new MyFragment(); case 2: return new MyOtherFragment(); } return null; } @Override public CharSequence getPageTitle(int position) { Locale l = Locale.getDefault(); switch (position) { case 0: return getString(R.string.tab_main_frag).toUpperCase(l); case 1: return getString(R.string.tab_my_frag).toUpperCase(l); case 2: return getString(R.string.tab_my_other_frag).toUpperCase(l); } return null; } } ... public static class MyFragment extends Fragment implements MyRVAdapter.OnEntryClickListener { ... private ArrayList<ItemObj> mArrayList; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ... doStuff(); ... } private void doStuff() { ... mArrayList = ...; MyRVAdapter adapter = new MyRVAdapter(getActivity(), mArrayList); adapter.setOnEntryClickListener(new MyRVAdapter.OnEntryClickListener() { @Override public void onEntryClick(View view, int position) { Intent intent = new Intent(getActivity(), MyActivity.class); intent.putExtra("INFORMATION", mArrayList.get(position)); startActivity(intent); } }); } ... } ... }
And here is part of my custom adapter:
public class MyRVAdapter extends RecyclerView.Adapter<MyRVAdapter.MyViewHolder> { public static class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { ... MyViewHolder(View itemView) { super(itemView); itemView.setOnClickListener(this); ... } @Override public void onClick(View v) { // The user may not set a click listener for list items, in which case our listener // will be null, so we need to check for this if (mOnEntryClickListener != null) { mOnEntryClickListener.onEntryClick(v, getLayoutPosition()); } } } private Context mContext; private ArrayList<ItemObj> mArray; public MyRVAdapter(Context context, ArrayList<ItemObj> array) { mContext = context; mArray = array; } @Override public int getItemCount() { return mArray.size(); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.tile_simple, parent, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { ItemObj anItem = mArray.get(position); ... } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); } private static OnEntryClickListener mOnEntryClickListener; public interface OnEntryClickListener { void onEntryClick(View view, int position); } public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) { mOnEntryClickListener = onEntryClickListener; } }
Here is the error in full:
01-23 14:07:59.083 388-388/com.mycompany.myapp E/AndroidRuntime: FATAL EXCEPTION: main Process: com.mycompany.myapp, PID: 388 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference at android.content.ComponentName.<init>(ComponentName.java:77) at android.content.Intent.<init>(Intent.java:4570) at com.mycompany.myapp.MyActivity$MyFragment$1.onEntryClick(MyActivity.java:783) at com.mycompany.myapp.adapter.MyRVAdapter$MyViewHolder.onClick(MyRVAdapter.java:42) at android.view.View.performClick(View.java:5197) at android.view.View$PerformClick.run(View.java:20926) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:145) at android.app.ActivityThread.main(ActivityThread.java:5951) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
The error points to the first line:
Intent intent = new Intent(getActivity(), MyActivity.class);
(from the fragment) first, with line after (in the error) pointing tomOnEntryClickListener.onEntryClick(v, getLayoutPosition());
from the overridenonClick
method in the custom adapter.I have also read similar answers, but they have not solved my issue.
Edit:
By using:
if (getActivity() == null) { Log.d(LOG_TAG, "Activity context is null"); } else { Intent intent = new Intent(getActivity(), MyActivity.class); intent.putExtra("INFORMATION", mArrayList.get(position)); startActivity(intent); }
in the inner class (
onEntryClick
) in the fragment, I found that callinggetActivity()
returnsnull
. -
Farbod Salamat-Zadeh over 8 yearsThanks for the answer. To be honest, for me right now it's almost midnight, so I'll get some sleep and test it out tomorrow. ;)
-
Farbod Salamat-Zadeh over 8 yearsYour solution didn't work for me. However, I mentioned in my answer that I have buttons which, when clicked, open the Activity. But I'm actually using a
RecyclerView
with a custom adapter I made, and the Activity is opened when I click on an item from that. The issue may be in the adapter because when I tested something what I had before with three buttons instead of the RecyclerView and adapter, it worked fine. The reason I didn't mention it before is that I assumed there would not be an issue with the adapter, so not including it would have made a simpler question. -
Farbod Salamat-Zadeh over 8 yearsI've updated my answer, I'm not sure if it helps, but I thought I might as well include the custom adapter if the problem is there.
-
Cory Charlton over 8 yearsThe problem likely is, sort of, there. Where do you set your
OnEntryClickListener
? -
Farbod Salamat-Zadeh over 8 yearsSorry - see my updated answer (I forgot to include it previously).
-
Cory Charlton over 8 yearsOk so then I assume that when you said "Your solution didn't work for me." that means that you tried to implement
OnEntryClickListener
on the fragment and replaced the anonymous method withthis
in youradapter.setOnEntryClickListener()
in `doStuff()? -
Cory Charlton over 8 yearsOk I provided a hack that might work as I've got nothing at this point :)
-
Farbod Salamat-Zadeh over 8 yearsThat solved that particular error, but resulted in a different one:
java.lang.IllegalStateException: Fragment MyFragment{18a42f07} not attached to Activity
. -
Cory Charlton over 8 yearsLet us continue this discussion in chat.
-
Farbod Salamat-Zadeh over 8 yearsI can't reference
openAnotherActivity
(non-static context) from a static context. Also, isMyApplication.getInstance()
meant to be from the other answer. -
ThaiPD over 8 yearsSo I think the problem is the static context. Why do you need to make the Holder as the static class while it can be in a normal context
-
Farbod Salamat-Zadeh over 8 yearsThank you so much! This solved my problem, but I also had to remove
static
from myViewHolder
as well. I also read up on this particular issue of static inner classes, and found a great answer about memory leaks and static/inner classes. -
Zhu almost 6 yearscan you please help me to fix this error stackoverflow.com/questions/51405397/… @MimmoGrottoli
-
David Wasser almost 6 years@FarbodSalamat-Zadeh actually there is no reason that you would need to remove
static
from yourViewholder
declaration. AViewholder
should be astatic class
, ie: just a data container with no behaviour (methods). If you are adding methods to aViewholder
that force you to remove thestatic
modifier from theclass
definition, it means that each and everyViewholder
object now has a reference to the outer class (in this case, the adapter). This is a waste of storage and means that your architecture is flawed. Just sayin'