SwipeRefreshLayout с EmptyView nullPointerException

Всякий раз, когда я прокручиваю вниз для обновления, я получаю исключение NullPointerException, но оно не в моем коде, а в методе startRefresh() из 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)

`

Это мой onCreate и onRefresh моей основной деятельности, 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);
}

Моя активность_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>`

Я искал и это только похожий вопрос, но решение не относится к моему случаю (по крайней мере, я так думаю). Любые подсказки? Заранее спасибо.


person Hugo M. Zuleta    schedule 14.07.2014    source источник


Ответы (2)


Тебе нужно иметь

context = this;

in onCreate

In

myListAdapter = new MyListAdapter(context, R.layout.row, monitored);// here you are using context

Context доступен после создания активности

Строка 441

mListener.onRefresh(); 

Глядя на источник

public void setOnRefreshListener(OnRefreshListener listener) {
    mListener = listener;
}

Итак, вы правильно реализовали OnRefreshListener в своей деятельности?

Как обсуждалось в чате

Удалите второй SwipeRefreshLayout

Чтобы установить пустой вид в список, прочитайте ниже вместо того, чтобы иметь другой swiperefreshlayout

http://cyrilmottier.com/2011/06/20/listview-tips-tricks-1-handle-emptiness/

person Raghunandan    schedule 14.07.2014
comment
Оно объявлено как поле над onCreate() final Context context = this; - person Hugo M. Zuleta; 14.07.2014
comment
@HugoM.Zuleta Context context является декларацией. Инициализируйте context =this в onCreate. Также он не должен быть окончательным. - person Raghunandan; 14.07.2014
comment
@HugoM.Zuleta нет. сделать это в onCreate это то, что я упоминал. - person Raghunandan; 14.07.2014
comment
По-прежнему получаю ошибку после выполнения вашей рекомендации. - person Hugo M. Zuleta; 14.07.2014
comment
@ HugoM.Zuleta это одна ошибка. - person Raghunandan; 14.07.2014
comment
@HugoM.Zuleta, вы можете посмотреть исходный код и проверить номер строки из трассировки стека и исправить проблему github.com/futuresimple/android-support-v4/blob/master/src/java/ - person Raghunandan; 14.07.2014
comment
Источник @HugoM.Zuleta намекает, что вы не реализовали OnRefreshListener в своей деятельности должным образом, и это в swipeLayout.setOnRefreshListener(this); относится к деятельности - person Raghunandan; 14.07.2014
comment
Активность реализует OnRefreshListener, и я переопределил этот метод. Это все там, прямо под onCreate() - person Hugo M. Zuleta; 14.07.2014
comment
Давайте продолжим обсуждение в чате. - person Raghunandan; 14.07.2014

Итак, после долгого разговора с пользователем Raghunandan здесь, он указал, что мой xml имеет два разных SwipeRefreshLayouts. Этот обходной путь использовался для правильной установки EmptyView в ListView (как показано в методе onCreate()), но все это было чушью. EmptyView работал, но один из этих SwipeRefreshLayouts имел нуль onRefreshListener (конечно, тот, что для EmptyView). ЭТО, естественно, вызвало исключение NullPointerException. Каждый фрагмент кода остается прежним. Единственное, что мне пришлось изменить, это 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" />

Примечание. Если у вас возникли проблемы с тем, что ContextMenus не отображается даже после правильного объявления, это должно исправить ситуацию.

Будьте осторожны с макетами!

person Hugo M. Zuleta    schedule 14.07.2014