0

我在我的应用程序中从 Parse.com 获取一些数据当它第一次启动时,它会检查缓存是否可用并显示它,然后用户可以拉动刷新以获取最新数据 当调用第一个刷新操作时,一切正常,但是当我第二次尝试刷新时,我得到 NetworkOnMainThreadException 强制关闭

这是调用方法(我正在使用 Android 支持的滑动刷新视图)

@Override
public void onRefresh() {
    // this part is merely a check, crashes both with or without this
    if(!runningTask.getClass().equals(AsyncTask.Status.FINISHED))
        runningTask.cancel(true);

    runningTask = new DownloadEvents(true).execute();
}

这是异步任务

private class DownloadEvents extends AsyncTask<Void, Void,  ArrayList<Event>> {
    boolean forceDownload;

    String errorString = "";
    public DownloadEvents(boolean forceDownload) {
        this.forceDownload = forceDownload;
        Parse.initialize(getActivity(), #API KEY CENSORED#);
    }

    // Do the long-running work in here
    protected ArrayList<Event> doInBackground(Void... params) {
        List<ParseObject> events = null;
        PreferencesHelper ph = new PreferencesHelper(getActivity());

        ParseQuery<ParseObject> eventsQuery = new ParseQuery<ParseObject>("events");
        try {
            eventsQuery.setCachePolicy(ParseQuery.CachePolicy.CACHE_ONLY);
            events = eventsQuery.find();
        } catch (ParseException e1) {
            e1.printStackTrace();
        }
        if(forceDownload || System.currentTimeMillis() - ph.getLastEventsDownloadTime() > 43200000 || events == null)
        {
            swipeLayout.setRefreshing(true);
            try {
                eventsQuery.setCachePolicy(ParseQuery.CachePolicy.NETWORK_ELSE_CACHE);
                events = eventsQuery.find();
                ph.setLastEventsDownloadTime();
            } catch (ParseException e) {
                e.printStackTrace();
            } 
        }

        // creating classes and sorting goes here

        return eventsList;
    }

    @Override
    protected void onPreExecute() { 
        super.onPreExecute(); 
    }

    @Override
    protected void onPostExecute(ArrayList<Event> events) {
        if(events.size() > 0)
        {
            EventsAdapter adapter = new EventsAdapter(getActivity(), R.layout.events_card, events);
            adapter.notifyDataSetChanged();
            getListView().setAdapter(adapter);
        }
        if(errorString != "")
            Toast.makeText(getActivity(), errorString, Toast.LENGTH_SHORT).show();

        swipeLayout.setRefreshing(false);
    }
}

即使我在应用程序启动时强制下载,它总是第二次下拉使其崩溃,而不是第二次下载某些东西

请不要建议关闭 NetworkOnMainThread 严格规则,这不是解决方案

编辑:这是logcat

FATAL EXCEPTION: main
Process: com.mdk.test, PID: 24048
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1145)
at com.android.org.conscrypt.OpenSSLSocketImpl.shutdownAndFreeSslNative(OpenSSLSocketImpl.java:1102)
at com.android.org.conscrypt.OpenSSLSocketImpl.close(OpenSSLSocketImpl.java:1097)
at org.apache.http.impl.SocketHttpClientConnection.close(SocketHttpClientConnection.java:205)
at org.apache.http.impl.conn.DefaultClientConnection.close(DefaultClientConnection.java:161)
at org.apache.http.impl.conn.tsccm.AbstractConnPool.closeConnection(AbstractConnPool.java:320)
at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.shutdown(ConnPoolByRoute.java:678)
at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.shutdown(ThreadSafeClientConnManager.java:256)
at com.parse.ParseRequest.initialize(ParseRequest.java:118)
at com.parse.Parse.initialize(Parse.java:109)
at com.mdk.test.EventsFragment$DownloadEvents.<init>(EventsFragment.java:136)
at com.mdk.test.EventsFragment.onRefresh(EventsFragment.java:223)
at android.support.v4.widget.SwipeRefreshLayout.startRefresh(SwipeRefreshLayout.java:441)
at android.support.v4.widget.SwipeRefreshLayout.onTouchEvent(SwipeRefreshLayout.java:399)
at android.view.View.dispatchTouchEvent(View.java:8073)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2253)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1987)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2259)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2001)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2259)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2001)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2259)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2001)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2259)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2001)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2259)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2001)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2198)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1649)
at android.app.Activity.dispatchTouchEvent(Activity.java:2717)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2159)
at android.view.View.dispatchPointerEvent(View.java:8263)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4013)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3892)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3454)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3473)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3583)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3481)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3640)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3454)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3507)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3473)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3481)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3454)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5682)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5656)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5627)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5761)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.view.InputEv
4

3 回答 3

0

很难准确判断问题出在哪里,因为您没有发布堆栈跟踪,但这一行看起来很可疑:

swipeLayout.setRefreshing(true);

您不能修改 doInBackground 上的任何视图,看起来这可能就是这样做的。

另一条鱼线是:

PreferencesHelper ph = new PreferencesHelper(getActivity());

显然,这个对象需要这个活动,这可能会或可能不会在以后导致 NetworkOnMainThread 异常。您不能在 doInBackGround 方法中触摸 UI。

只要保持 doInBackground 干净,只在那里做网络的东西,不要和其他东西纠缠在一起。

于 2014-07-03T22:33:16.710 回答
0

Parse.initialize()位于异步任务构造函数中,该构造函数在主线程中执行并调用网络操作。

将呼叫移至doInBackground()

于 2014-07-05T09:20:54.517 回答
0
event.size()

对于空数据将引发异常错误,但不确定这是否是您面临的确切问题。

于 2014-07-05T09:24:43.517 回答