【问题标题】:NetworkOnMainThreadException even after using asynctaskNetworkOnMainThreadException 即使在使用 asynctask 之后
【发布时间】:2017-06-25 19:49:51
【问题描述】:

我在 stackOverflow 中发现了一些与此主题相关的问题,但无法找到合适的答案。在我的应用程序中,我打算通过单独的线程进行网络通信。所以我使用了 asynctask。但即使在使用 asynctask 之后,我也找到了networkOnMainThreadException。这是我的代码:

private static final String CATEGORY_ALL_FETCHING_URL = "http://qpon.es/coupon/index.php/welcome/categories/all";
private static final String CATEGORY_IMAGE_URL = "http://qpon.es/images/coupons/";
private static final String TAG_CATEGORY_ID = "id";
private static final String TAG_CATEGORY_NAME = "name";
private static final String TAG_CATEGORY_IMAGE = "img";
private static final String TAG_CATEGORY_CREATE_DATE = "created";
private static final String CATEGORY_INTENT = "category";

private ProgressDialog downloadingStatusIndicator = null;
private ArrayList<Category> categoryList = null;
private CustomCategoryAdapter customAdapter = null;

private class CateoryListDataGenerator extends
        AsyncTask<String, Void, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        downloadingStatusIndicator = new ProgressDialog(getActivity());
        downloadingStatusIndicator.setTitle(R.string.categoryDownloadTitle);
        downloadingStatusIndicator.setMessage("Retrieving Categories...");
        downloadingStatusIndicator.show();

    }

    @Override
    protected String doInBackground(String... params) {
        // TODO Auto-generated method stub
        String response = "";
        try {

            Log.d("BACK THREAD STARTS", "YES");
            categoryList = new ArrayList<Category>();
            response = JSONParser
                    .getRemoteResponse(CATEGORY_ALL_FETCHING_URL);

            // Thread.sleep(2000);
        } catch (Exception e) {

            Log.d("BACKGROUD", e.getMessage());
        }

        return response;
    }

    @Override
    protected void onPostExecute(String response) {

        JSONArray categoriesJSON = null;
        try {
            categoriesJSON = new JSONArray(response);
        } catch (JSONException e) {
            Log.e("JSON Parser", "Error parsing data " + e.toString());
        }

        for (int i = 0; i < categoriesJSON.length(); i++) {

            Log.d("LOOP BEGINS", "YES");
            Category eachCategory = new Category();

            JSONObject eachCategoryJSON = null;
            try {
                eachCategoryJSON = categoriesJSON.getJSONObject(i);
                eachCategory.setCategoryName(eachCategoryJSON
                        .getString(TAG_CATEGORY_NAME));
                eachCategory.setCategoryCreateDate(eachCategoryJSON
                        .getString(TAG_CATEGORY_CREATE_DATE));
                eachCategory.setCategoryImagePath(CATEGORY_IMAGE_URL
                        + eachCategoryJSON.getString(TAG_CATEGORY_IMAGE));
                eachCategory.setCategoryID(eachCategoryJSON
                        .getInt(TAG_CATEGORY_ID));
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            categoryList.add(eachCategory);
            Log.d("CATEGORY INSERTED", categoryList.toString());
        }

        Log.d("CATEGORY LIST", categoryList.toString());

        if (categoryList != null || categoryList.size() > 0) {
            customAdapter.notifyDataSetChanged();

            for (int i = 0; i < categoryList.size(); i++) {
                customAdapter.add(categoryList.get(i));

            }

            downloadingStatusIndicator.dismiss();
            customAdapter.notifyDataSetChanged();
        }

        Toast.makeText(getActivity(), response, Toast.LENGTH_SHORT).show();

    }

}

在 JSONParder 的 setRemoteRenponse() 方法中:

boolean isURLFetched = false;

    while(!isURLFetched){

        DefaultHttpClient client = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(url);
        try {
            HttpResponse execute = client.execute(httpGet);
            content = execute.getEntity().getContent();
            isURLFetched = true;

        } catch (UnsupportedEncodingException e) {

            Log.d("HERE", "ONE");
            e.printStackTrace();
        } catch (ClientProtocolException e) {

            Log.d("HERE", "TWO");
            e.printStackTrace();
        } catch (IOException e) {

            Log.d("HERE", "THREE");
            e.printStackTrace();
        }
    }

    try {

        BufferedReader buffer = new BufferedReader(new InputStreamReader(
                content));
        String s = "";
        while ((s = buffer.readLine()) != null) {
            response += s;
        }

    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }

    return response;

最后在片段的 onActivityCreated() 方法中创建并执行 asynctask 类对象:

CateoryListDataGenerator dataGenerator = new CateoryListDataGenerator();
dataGenerator.execute(new String[] { CATEGORY_ALL_FETCHING_URL });     

我在这里做错了吗?我也包含了 INTERNET 权限。目前,我已更改线程策略以在 android 3.0 或更高版本上运行此应用,但这不是解决方案。

这里是 logcat 消息:

05-24 17:11:36.025: E/AndroidRuntime(708): FATAL EXCEPTION: main
05-24 17:11:36.025: E/AndroidRuntime(708): android.os.NetworkOnMainThreadException
05-24 17:11:36.025: E/AndroidRuntime(708):  at     android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
05-24 17:11:36.025: E/AndroidRuntime(708):  at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
05-24 17:11:36.025: E/AndroidRuntime(708):  at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
05-24 17:11:36.025: E/AndroidRuntime(708):  at java.net.InetAddress.getAllByName(InetAddress.java:214)
05-24 17:11:36.025: E/AndroidRuntime(708):  at libcore.net.http.HttpConnection.<init>(HttpConnection.java:70)
05-24 17:11:36.025: E/AndroidRuntime(708):  at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)
05-24 17:11:36.025: E/AndroidRuntime(708):  at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:341)
05-24 17:11:36.025: E/AndroidRuntime(708):  at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)
05-24 17:11:36.025: E/AndroidRuntime(708):  at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
05-24 17:11:36.025: E/AndroidRuntime(708):  at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:315)
05-24 17:11:36.025: E/AndroidRuntime(708):  at libcore.net.http.HttpEngine.connect(HttpEngine.java:310)
05-24 17:11:36.025: E/AndroidRuntime(708):  at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:289)
05-24 17:11:36.025: E/AndroidRuntime(708):  at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:239)
05-24 17:11:36.025: E/AndroidRuntime(708):  at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:273)
05-24 17:11:36.025: E/AndroidRuntime(708):  at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:168)
05-24 17:11:36.025: E/AndroidRuntime(708):  at com.example.couponapp.adapters.CustomCategoryAdapter.getScaledBitmapFromFile(CustomCategoryAdapter.java:83)
05-24 17:11:36.025: E/AndroidRuntime(708):  at com.example.couponapp.adapters.CustomCategoryAdapter.getView(CustomCategoryAdapter.java:58)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.AbsListView.obtainView(AbsListView.java:2267)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.ListView.makeAndAddView(ListView.java:1769)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.ListView.fillDown(ListView.java:672)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.ListView.fillFromTop(ListView.java:733)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.ListView.layoutChildren(ListView.java:1608)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.AbsListView.onLayout(AbsListView.java:2102)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.View.layout(View.java:13754)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.ViewGroup.layout(ViewGroup.java:4362)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.RelativeLayout.onLayout(RelativeLayout.java:948)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.View.layout(View.java:13754)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.ViewGroup.layout(ViewGroup.java:4362)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.View.layout(View.java:13754)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.ViewGroup.layout(ViewGroup.java:4362)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.View.layout(View.java:13754)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.ViewGroup.layout(ViewGroup.java:4362)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1649)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1507)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.LinearLayout.onLayout(LinearLayout.java:1420)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.View.layout(View.java:13754)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.ViewGroup.layout(ViewGroup.java:4362)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.View.layout(View.java:13754)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.ViewGroup.layout(ViewGroup.java:4362)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1866)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1687)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4212)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.Choreographer.doCallbacks(Choreographer.java:555)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.Choreographer.doFrame(Choreographer.java:525)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.os.Handler.handleCallback(Handler.java:615)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.os.Handler.dispatchMessage(Handler.java:92)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.os.Looper.loop(Looper.java:137)
05-24 17:11:36.025: E/AndroidRuntime(708):  at android.app.ActivityThread.main(ActivityThread.java:4745)
05-24 17:11:36.025: E/AndroidRuntime(708):  at java.lang.reflect.Method.invokeNative(Native Method)
05-24 17:11:36.025: E/AndroidRuntime(708):  at java.lang.reflect.Method.invoke(Method.java:511)
05-24 17:11:36.025: E/AndroidRuntime(708):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
05-24 17:11:36.025: E/AndroidRuntime(708):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
05-24 17:11:36.025: E/AndroidRuntime(708):  at dalvik.system.NativeStart.main(Native Method)

【问题讨论】:

  • 请发布整个堆栈跟踪。
  • 你在哪里调用 setRemoteRenponse()?
  • @Raghunandan 可能他的意思是 getRemoteRenponse() ?
  • @blackbelt 同意了。他正在尝试进行网络相关操作 HttpResponse execute = client.execute(httpGet);在 setRemoteRenponse() 中,所以可能在 ui 线程上调用该方法
  • @Raghunandan HttpGet httpGet = new HttpGet(url);可以在 UI 线程上运行。是必须在不同线程上运行的执行方法

标签: android android-fragments android-asynctask


【解决方案1】:

看起来问题不在这里。从日志中,从适配器内部,

05-24 17:11:36.025: E/AndroidRuntime(708): 在 libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:168) 05-24 17:11:36.025: E/AndroidRuntime(708): 在 com.example.couponapp.adapters.CustomCategoryAdapter.getScaledBitmapFromFile(CustomCategoryAdapter.java:83) 05-24 17:11:36.025: E/AndroidRuntime(708): at com.example.couponapp.adapters.CustomCategoryAdapter.getView(CustomCategoryAdapter.java:58) 05-24 17:11:36.025: E/AndroidRuntime(708): 在 android.widget.AbsListView.obtainView(AbsListView.java:2267)

您可以看到 getView() 方法正在尝试加载图像,而该方法又会发出网络请求以从某处获取图像。

检查您在此处的具体操作。

com.example.couponapp.adapters.CustomCategoryAdapter.getScaledBitmapFromFile(CustomCategoryAdapter.java:83) 05-24 17:11:36.025: E/AndroidRuntime(708): at com.example.couponapp.adapters.CustomCategoryAdapter.getView(CustomCategoryAdapter.java:58)

在 getScaledBitmapFromFile 方法中,我怀疑您正在进行网络调用,它在 UIThread 上。

【讨论】:

  • 谢谢!!....@Kumar Bibek。你是对的。所以我必须在单独的线程中下载图像。但是虽然我注释掉了图像下载部分,我的 logcat 仍然显示“你的应用程序可能在它的主线程上做了太多的工作”。它应该是显示?我仍然是使用 asynctask 的新手,所以如果问题很愚蠢,请原谅我...... :)
【解决方案2】:

请将 onPostExecute 中的代码放回 doInBackground 并在 onPostExecute 中返回您想要放入适配器的结果。

您的问题必须是 JSONArray,请参阅文档...它不是线程安全的 ;)。

【讨论】:

  • 就像 +Kumar Bibek 所说,getScaledBitmapFromFile(...) 也可能是问题所在。 File-Operations 也调用 NetworkOnThreadMainException!
【解决方案3】:

如果答案是 Luserdroid 不清楚,那么: 你应该把你的处理代码放在doInBackground里面,我把处理代码放在onPostExecute里面是错误的,它是由主线程执行的,因此我遇到了同样的问题。

【讨论】:

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