【问题标题】:Android AsyncTask getting NetworkOnMainThreadException when called a second timeAndroid AsyncTask 在第二次调用时获取 NetworkOnMainThreadException
【发布时间】:2014-07-03 22:20:54
【问题描述】:

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

【问题讨论】:

  • Please don't suggest turning off the NetworkOnMainThread strict rule, 这是什么意思?你现在有吗?
  • if(errorString != "") 那是无效代码。改为if(!errorString.equals(""))
  • 请发布stacktrace/logcat。
  • return eventsList;?那是什么?为什么不return events
  • NetworkOnMainThreadException 通常意味着:主线程上的网络(此代码似乎无法导致)。请发布 logcat 堆栈跟踪。

标签: android android-asynctask parse-platform networkonmainthread


【解决方案1】:

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

将电话转至doInBackground()

【讨论】:

  • 是的,我现在只是在玩它,试图将它移到 doInBackground() 中,当然它现在工作正常,我回到这个页面发布结果...为什么它不会在第一次调用时使应用程序崩溃?
  • 猜测:可能第一次调用已经在后台线程上,或者不太可能,初始化并不总是调用网络操作。
  • 我打赌你的第二个猜测,第一次初始化可能不需要连接,但如果你尝试通过重新初始化来“重置”它,它会尝试上网并获得一个新的令牌排序
【解决方案2】:

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

swipeLayout.setRefreshing(true);

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

另一条鱼线是:

PreferencesHelper ph = new PreferencesHelper(getActivity());

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

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

【讨论】:

  • 这些都是好点,但它们不会触发任何错误(我没有注意到)并且它们在第一次刷新时工作得很好,这对我来说又没有意义,就像只有第二次拉动导致崩溃
【解决方案3】:
event.size()

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-16
    • 2015-01-01
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多