Reputation: 13442
Note: I know that this question is a duplicate and you are probably encouraged to downvote it but,
I recently deployed my APK on playstore and received NullPointerException
for a very few users(4):
Exception java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Object.equals(java.lang.Object)' on a null object reference
android.widget.AdapterView.getPositionForView (AdapterView.java:607)
com.snap.testsnapboard.AlbumSelectActivity$1.onItemClick (AlbumSelectActivity.java:114)
android.widget.AdapterView.performItemClick (AdapterView.java:305)
android.widget.AbsListView.performItemClick (AbsListView.java:1146)
android.widget.AbsListView$PerformClick.run (AbsListView.java:3057)
android.widget.AbsListView.onTouchUp (AbsListView.java:3876)
android.widget.AbsListView.onTouchEvent (AbsListView.java:3641)
android.view.View.dispatchTouchEvent (View.java:8481)
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2400)
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2093)
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2406)
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2107)
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2406)
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2107)
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2406)
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2107)
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2406)
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2107)
com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent (PhoneWindow.java:2369)
com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent (PhoneWindow.java:1719)
android.app.Activity.dispatchTouchEvent (Activity.java:2785)
com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent (PhoneWindow.java:2330)
android.view.View.dispatchPointerEvent (View.java:8676)
android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent (ViewRootImpl.java:4141)
android.view.ViewRootImpl$ViewPostImeInputStage.onProcess (ViewRootImpl.java:4007)
android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3562)
android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:3615)
android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:3581)
android.view.ViewRootImpl$AsyncInputStage.forward (ViewRootImpl.java:3698)
android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:3589)
android.view.ViewRootImpl$AsyncInputStage.apply (ViewRootImpl.java:3755)
android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3562)
android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:3615)
android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:3581)
android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:3589)
android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3562)
android.view.ViewRootImpl.deliverInputEvent (ViewRootImpl.java:5825)
android.view.ViewRootImpl.doProcessInputEvents (ViewRootImpl.java:5799)
android.view.ViewRootImpl.enqueueInputEvent (ViewRootImpl.java:5770)
android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent (ViewRootImpl.java:5915)
android.view.InputEventReceiver.dispatchInputEvent (InputEventReceiver.java:185)
android.os.MessageQueue.nativePollOnce (MessageQueue.java)
android.os.MessageQueue.next (MessageQueue.java:143)
android.os.Looper.loop (Looper.java:122)
android.app.ActivityThread.main (ActivityThread.java:5254)
java.lang.reflect.Method.invoke (Method.java)
java.lang.reflect.Method.invoke (Method.java:372)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:902)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:697)
This exception originates in the line while ((v = (View) listItem.getParent()) != null && !v.equals(this)) {
in AdapterView.java
:
/**
* Returns the position within the adapter's data set for the view, where
* view is a an adapter item or a descendant of an adapter item.
* <p>
* <strong>Note:</strong> The result of this method only reflects the
* position of the data bound to <var>view</var> during the most recent
* layout pass. If the adapter's data set has changed without a subsequent
* layout pass, the position returned by this method may not match the
* current position of the data within the adapter.
*
* @param view an adapter item, or a descendant of an adapter item. This
* must be visible in this AdapterView at the time of the call.
* @return the position within the adapter's data set of the view, or
* {@link #INVALID_POSITION} if the view does not correspond to a
* list item (or it is not currently visible)
*/
public int getPositionForView(View view) {
View listItem = view;
try {
View v;
while ((v = (View) listItem.getParent()) != null && !v.equals(this)) {
listItem = v;
}
} catch (ClassCastException e) {
// We made it up to the window without find this list view
return INVALID_POSITION;
}
if (listItem != null) {
// Search the children for the list item
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
if (getChildAt(i).equals(listItem)) {
return mFirstPosition + i;
}
}
}
// Child not found!
return INVALID_POSITION;
}
Other things worth mentioning:
addFooterView()
For this, I have written the following code:
// Since we have a Footer view attached to the ListView, the position selected
// might not always map 1-to-1 with the ArrayList we are using to represent the
// Album model objects list. Lets check if the Footer view has been selected and
// in this case, do nothing.
if(myListView.getPositionForView(loadMoreView) == arg2){
// Blank return
return;
}
This is the code that ultimately calls the method inside the AdapterView.java
. Now, why would there be a NullPointerException
when there is a null check in the while loop and all the UI processing happens in the main thread only?
Upvotes: 1
Views: 2041
Reputation: 11
I had to overwrite the method, i just found this question today but i had line 665 and did not see an answer
My best guess is the fix was not in certain API but by importing the method from API 27 and modifying it slightly to pass in the Adapter
public int getPositionForView(View view, AdapterView av)
{
View listItem = view;
try
{
View v;
while ((v = (View) listItem.getParent()) != null && !v.equals(av))
{
listItem = v;
}
}
catch (ClassCastException e)
{
// We made it up to the window without find this list view
return -1;
}
if (listItem != null)
{
// Search the children for the list item
final int childCount = av.getChildCount();
for (int i = 0; i < childCount; i++)
{
if (av.getChildAt(i).equals(listItem))
{
return av.getFirstVisiblePosition() + i;
}
}
}
// Child not found!
return -1;
}
it always works
Upvotes: 1
Reputation: 4079
I want to tell you few tips about null pointer exception.
if listItem is null, it will create exception...if listItem is not null but listItem.getParent() is null, it will also create exception...or either when you cast any object to another and which is null..it throws exception.
(v = (View) listItem.getParent()) != null && !v.equals(this)
In your case, listItem.getParent() is null that's why it throws exception.
you should do like this:
if(v != null && listItem != null && listItem.getParent() != null && (v = (View) listItem.getParent()) != null && !v.equals(this) {
}
I hope it will not throw exception.
Upvotes: 1
Reputation: 12636
If parameter view is null then listItem also will be null. It'll cause NPE here:
listItem.getParent() != null
Upvotes: 0