我正在尝试从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)
答案 0 :(得分:0)
因为您正在从doInBackGround方法触摸GridView,这是不允许的。
将以下行移至onPostExecute
mGridView.setEmptyView(mRootView.findViewById(android.R.id.empty));
阅读此官方文件
答案 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);