在android.os.AsyncTask $ 3.done上执行doInBackground()时发生错误

时间:2017-02-16 04:56:21

标签: android

我正在尝试从OK Cupid json文件中选择数据,但我最终得到:

  

在android.os.AsyncTask $ 3.done执行doInBackground()时发生错误。

以下是代码

public class MainActivityFragment extends Fragment{
        private static final String URL = "http://www.okcupid.com/matchSample.json";
        private static final String TAG = "MainActivityFragment";
        private Context mContext;
        private GridView mGridView;
        private AsyncTask<Void, Void, List<Person>> mAsyncTask;
        private View mRootView;

        public MainActivityFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);

            mContext = this.getContext();
            mRootView = rootView;
            mGridView = (GridView) rootView.findViewById(R.id.grid_view);
            //similar to how the real app works on orientation change
            checkConfiguration();
            return rootView;
        }
        private class GetPersonInformation extends AsyncTask<Void, Void, List<Person>> {
            @Override
            protected List<Person> doInBackground(Void... params) {
                try {
                    return getPeople();
                } catch (IOException e) {
                    Log.e("GetPersonInformation", "IOException in doInBackground");
                    //cancel asynctask
                    cancel(true);
                    return null;
                }
            }
            @Override
            protected void onPostExecute(List<Person> people) {
                RelativeLayout progressLayout = (RelativeLayout) mRootView.findViewById(R.id.progress_layout);
                progressLayout.setVisibility(View.GONE);
                if (people != null) {
                    ItemAdapter itemAdapter = new ItemAdapter(mContext, R.id.grid_view, people);
                    mGridView.setAdapter(itemAdapter);
                    mGridView.setVisibility(View.VISIBLE);
                } else {
                    mGridView.setEmptyView(mRootView.findViewById(android.R.id.empty));
                }
            }
            @Override
            protected void onCancelled(List<Person> people) {
                mGridView.setEmptyView(mRootView.findViewById(android.R.id.empty));
            }
        }
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);

            checkConfiguration();
            //onDestroy() not called when doing configChanges so putting the below here
            AsyncTask.Status status = mAsyncTask.getStatus();
            if (status == AsyncTask.Status.PENDING || status == AsyncTask.Status.RUNNING) {
                mAsyncTask.cancel(true);
            }
        }
        public void checkConfiguration() {
            int orientation = getResources().getConfiguration().orientation;
            if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                mGridView.setNumColumns(3);
            } else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                mGridView.setNumColumns(2);
            }
        }
        @Override
        public void onStart() {
            super.onStart();

            mAsyncTask = new GetPersonInformation();
            mAsyncTask.execute();
        }
        public List<Person> getPeople() throws IOException {
            ConnectivityManager connMgr = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
            if (networkInfo != null && networkInfo.isConnected()) {
                // Create a new HTTP connection to download JSON
                HttpURLConnection urlConnection = null;
                String result = null;
                int resCode;
                try {
                    java.net.URL url = new URL(URL);
                    urlConnection = (HttpURLConnection) url.openConnection();
                    urlConnection.setAllowUserInteraction(false);
                    urlConnection.setInstanceFollowRedirects(true);

                    resCode = urlConnection.getResponseCode();

                    if (resCode == HttpURLConnection.HTTP_OK) {
                        BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
                        StringBuilder sb = new StringBuilder();
                        String line;
                        while ((line = br.readLine()) != null) {
                            sb.append(line).append("\n");
                        }
                        br.close();
                        result = sb.toString();
                    }
                } catch (MalformedURLException e) {
                    Log.e(TAG, "Malformed URL");
                } catch (IOException e) {
                    Log.e(TAG, "IOException");
                } finally {
                    if (urlConnection != null) {
                        try {
                            urlConnection.disconnect();
                        } catch (Exception e) {
                            Log.e(TAG, getResources().getString(R.string.disconnect_error));
                        }
                    }
                }
                if (result == null) {
                    mGridView.setEmptyView(mRootView.findViewById(android.R.id.empty));
                    return null;
                }
                return readJSON(result);
            }
            return null;
        }
        public List<Person> readJSON(String response) {
            try {
                JSONObject json = (JSONObject) new JSONTokener(response).nextValue();
                JSONArray jsondataArray = json.getJSONArray("data");
                List<Person> people = new ArrayList<Person>();
                int jsondataArrayLength = jsondataArray.length();
                String imageURL = null;
                String city = null;
                String state = null;
                String userName = null;
                int matchPercentage = 0;
                int age = 0;

                for (int i = 0; i < jsondataArrayLength; i++) {
                    JSONObject o = jsondataArray.getJSONObject(i);
                    if (o.optJSONObject("location") != null) {
                        JSONObject location = o.getJSONObject("location");
                        if (!location.optString("city_name").equals("")) {
                            city = location.getString("city_name");
                        }
                        if (!location.optString("state_code").equals("")) {
                            state = location.getString("state_code");
                        }
                    }
                    if (o.optInt("match") != 0) {
                        matchPercentage = o.getInt("match");
                    }
                    if (o.optInt("age") != 0) {
                        age = o.getInt("age");
                    }
                    if (!o.optString("username").equals("")) {
                        userName = o.getString("username");
                    }
                    if (o.optJSONObject("photo") != null) {
                        JSONObject photos = o.getJSONObject("photo");
                        if (photos.optJSONObject("thumb_paths") != null) {
                            JSONObject thumbPaths = photos.getJSONObject("thumb_paths");
                            if (!thumbPaths.optString("large").equals("")) {
                                imageURL = thumbPaths.getString("large");
                            }
                        }
                    }
                    people.add(new Person(userName, imageURL, age, city, state, matchPercentage));
                    imageURL = null;
                    city = null;
                    state = null;
                    matchPercentage = 0;
                    userName = null;
                    age = 0;
                }
                return people;
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

发生错误:

02-16 06:55:00.959 7880-7908/com.johnbohne.okcupid E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
                                                                     Process: com.johnbohne.okcupid, PID: 7880
                                                                     java.lang.RuntimeException: An error occurred while executing doInBackground()
                                                                         at android.os.AsyncTask$3.done(AsyncTask.java:325)
                                                                         at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                                                                         at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                                                                         at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                                                                         at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
                                                                         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                                                                         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                         at java.lang.Thread.run(Thread.java:761)
                                                                      Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                                                                         at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6891)
                                                                         at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1048)
                                                                         at android.view.View.requestLayout(View.java:19781)
                                                                         at android.view.View.requestLayout(View.java:19781)
                                                                         at android.view.View.requestLayout(View.java:19781)
                                                                         at android.view.View.requestLayout(View.java:19781)
                                                                         at android.view.View.requestLayout(View.java:19781)
                                                                         at android.view.View.requestLayout(View.java:19781)
                                                                         at android.view.View.requestLayout(View.java:19781)
                                                                         at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
                                                                         at android.view.View.requestLayout(View.java:19781)
                                                                         at android.view.View.setFlags(View.java:11478)
                                                                         at android.view.View.setVisibility(View.java:8069)
                                                                         at android.widget.AdapterView.updateEmptyStatus(AdapterView.java:763)
                                                                         at android.widget.AdapterView.setEmptyView(AdapterView.java:687)
                                                                         at com.johnbohne.okcupid.MainActivityFragment.getPeople(MainActivityFragment.java:154)
                                                                         at com.johnbohne.okcupid.MainActivityFragment$GetPersonInformation.doInBackground(MainActivityFragment.java:63)
                                                                         at com.johnbohne.okcupid.MainActivityFragment$GetPersonInformation.doInBackground(MainActivityFragment.java:59)
                                                                         at android.os.AsyncTask$2.call(AsyncTask.java:305)
                                                                         at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                         at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
                                                                         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
                                                                         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                                                                         at java.lang.Thread.run(Thread.java:761) 

3 个答案:

答案 0 :(得分:0)

因为您正在从doInBackGround方法触摸GridView,这是不允许的。

将以下行移至onPostExecute

mGridView.setEmptyView(mRootView.findViewById(android.R.id.empty));

阅读此官方文件

  1. 线程规则https://developer.android.com/reference/android/os/AsyncTask.html

  2. https://developer.android.com/training/multiple-threads/communicate-ui.html

答案 1 :(得分:0)

doInBackground(Void... params) 

在后台线程(工作线程)上运行,意味着在完成任务后它返回onPostExecute()方法的结果。如果更新任何UI元素,则应仅在主线程(UI线程)上更新。

在您的代码中包含以下行

mGridView.setEmptyView(mRootView.findViewById(android.R.id.empty));

gridview是UI元素。你不应该在工作线程上做。您可以更新onPostExecute()方法,因为它在主线程(UI线程)上运行。

答案 2 :(得分:0)

添加以下oncancelled后代码工作。 onCanceled上显示错误

 RelativeLayout progressLayout = (RelativeLayout) mRootView.findViewById(R.id.progress_layout);
 progressLayout.setVisibility(View.GONE);