Android AsyncTask在第二次调用时获取NetworkOnMainThreadException

时间:2014-07-03 22:20:55

标签: android android-asynctask parse-platform networkonmainthread

我在我的应用中从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

3 个答案:

答案 0 :(得分:0)

很难确切地说出问题出在哪里,因为你没有发布堆栈跟踪,但这一行看起来很可疑:

swipeLayout.setRefreshing(true);

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

另一条可疑线是:

PreferencesHelper ph = new PreferencesHelper(getActivity());

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

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

答案 1 :(得分:0)

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

将通话移至doInBackground()

答案 2 :(得分:0)

event.size()

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