问题
Whenever I swipe down to refresh, I get a NullPointerException but it's not in my code, rather in the startRefresh() method from SwipeRefreshLayout.
07-14 11:55:06.714: E/AndroidRuntime(20484): java.lang.NullPointerException
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.support.v4.widget.SwipeRefreshLayout.startRefresh(SwipeRefreshLayout.java:441)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.support.v4.widget.SwipeRefreshLayout.onTouchEvent(SwipeRefreshLayout.java:399)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.View.dispatchTouchEvent(View.java:7253)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2168)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1903)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
07-14 11:55:06.714: E/AndroidRuntime(20484): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2215)
07-14 11:55:06.714: E/AndroidRuntime(20484): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1458)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.app.Activity.dispatchTouchEvent(Activity.java:2410)
07-14 11:55:06.714: E/AndroidRuntime(20484): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2163)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.View.dispatchPointerEvent(View.java:7433)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3220)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3165)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4292)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4271)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4363)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:179)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:171)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:4342)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:4382)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.Choreographer.doCallbacks(Choreographer.java:562)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.Choreographer.doFrame(Choreographer.java:530)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.os.Handler.handleCallback(Handler.java:725)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.os.Handler.dispatchMessage(Handler.java:92)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.os.Looper.loop(Looper.java:137)
07-14 11:55:06.714: E/AndroidRuntime(20484): at android.app.ActivityThread.main(ActivityThread.java:5227)
07-14 11:55:06.714: E/AndroidRuntime(20484): at java.lang.reflect.Method.invokeNative(Native Method)
07-14 11:55:06.714: E/AndroidRuntime(20484): at java.lang.reflect.Method.invoke(Method.java:511)
07-14 11:55:06.714: E/AndroidRuntime(20484): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
07-14 11:55:06.714: E/AndroidRuntime(20484): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
07-14 11:55:06.714: E/AndroidRuntime(20484): at dalvik.system.NativeStart.main(Native Method)
`
This is my onCreate and onRefresh of my main Activity, MonitoredCoursesActivity:
public class MonitoredCoursesActivity extends ListActivity implements OnRefreshListener {
private SwipeRefreshLayout swipeLayout;
private ArrayList<Course> monitored;
private String lastUpdate;
private ListView myList;
private MyListAdapter myListAdapter;
final Context context = this;
// private int freqUpdate;
// private String updateTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (loadState()==null) {
monitored = new ArrayList<Course>();
}
myList=(ListView)findViewById(android.R.id.list);
myListAdapter = new MyListAdapter(context, R.layout.row, monitored);
View empty = findViewById(android.R.id.empty);
myList.setEmptyView(empty);
myList.setAdapter(myListAdapter);
myList.setLongClickable(true);
registerForContextMenu(myList);
swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorScheme(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
swipeLayout.setHapticFeedbackEnabled(true);
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override public void run() {
//Refresh all courses in the list
updateCoursesInfo();
swipeLayout.setRefreshing(false);
}
}, 10000);
}
My activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:text="@string/courses" >
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="2"
android:cacheColorHint="#000000"
android:divider="#D5DDDE"
android:dividerHeight="1dp"
android:drawSelectorOnTop="false"
android:focusableInTouchMode="false"
android:footerDividersEnabled="false"
android:headerDividersEnabled="true"
android:listSelector="@android:color/transparent" />
</android.support.v4.widget.SwipeRefreshLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout_emptyView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarStyle="outsideOverlay" >
<TextView
android:id="@android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:alpha="0.18"
android:clickable="false"
android:gravity="center|center_vertical|center_horizontal"
android:longClickable="false"
android:text="@string/empty_list"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/widget_edittext_dark"
android:textSize="35sp"
android:textStyle="bold"
android:typeface="normal" />
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
My row.xml for ListView items:
`
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="2" >
<TextView
android:id="@+id/txtCourseName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_marginBottom="2dp"
android:paddingRight="5dp"
android:text="@string/section"
android:textSize="25sp" />
<TextView
android:id="@+id/txtSection"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_gravity="center"
android:layout_row="0"
android:text="@string/section"
android:textAppearance="?android:attr/textAppearanceMedium" />
</GridLayout>
<TextView
android:id="@+id/txtRemaining"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="68dp"
android:text="@string/remaining"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/txtCRN"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/crn"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/txtFecha"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>`
I've searched and this is the only similar question, but the solution doesn't apply to my case (or at least I think so). Any clues? Thanks in advance.
回答1:
You need to have
context = this;
in onCreate
In
myListAdapter = new MyListAdapter(context, R.layout.row, monitored);// here you are using context
Context is available once activity is created
Line 441 is
mListener.onRefresh();
Looking at the source
public void setOnRefreshListener(OnRefreshListener listener) {
mListener = listener;
}
So have you implemented OnRefreshListener properly in your Activity?
As discussed in the chat
Remove the second SwipeRefreshLayout
To set a empty view to listview read the below instead of having the other swiperefreshlayout
http://cyrilmottier.com/2011/06/20/listview-tips-tricks-1-handle-emptiness/
回答2:
So, after a long talk with user Raghunandan here, he pointed out that my xml had two different SwipeRefreshLayouts. This workaround was used in order to properly set an EmptyView on the ListView (as shown on the onCreate() method), but was all rubbish. The EmptyView worked, but one of those SwipeRefreshLayouts had a null onRefreshListener (the one for the EmptyView, of course). THIS caused the NullPointerException, naturally. Every piece of code remains the same. The only thing I had to change was the activity_main.xml:
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:text="@string/courses" >
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="2"
android:cacheColorHint="#000000"
android:divider="#D5DDDE"
android:dividerHeight="1dp"
android:drawSelectorOnTop="false"
android:focusableInTouchMode="false"
android:footerDividersEnabled="false"
android:headerDividersEnabled="true"
android:listSelector="@android:color/transparent" />
</android.support.v4.widget.SwipeRefreshLayout>
<TextView
android:id="@android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:alpha="0.18"
android:clickable="false"
android:gravity="center|center_vertical"
android:longClickable="false"
android:text="@string/empty_list"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/widget_edittext_dark"
android:textSize="35sp"
android:textStyle="bold"
android:typeface="normal" />
Note: If you're having issues with ContextMenus not appearing, even after being correctly declared, this should fix it.
Be careful with your layouts!
来源:https://stackoverflow.com/questions/24742031/swiperefreshlayout-with-emptyview-nullpointerexception