我从Android Hive获得了一个代码来解析来自url的JSON数据。然后我试图在Rotten Tomatoes Upcoming Movies Api上实现相同的代码。我已经实现了相同的代码,几乎根据我的需要修改了所有的xml文件。但问题是当我试图运行代码时,它显示出NetworkOnMainThread Exception。
这是我的代码。
public class Upcoming extends ListActivity
{
String url = "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/upcoming.json?apikey=yvvgsv722gy2zkey3ebkda5t";
final String TAG_MOVIES = "movies";
final String TAG_ID = "id";
final String TAG_TITLE = "title";
final String TAG_YEAR = "year";
final String TAG_MPAA_RATING = "mpaa_rating";
final String TAG_RUNTIME = "runtime";
final String TAG_RELEASE_DATES = "release_dates";
final String TAG_RATINGS = "ratings";
final String TAG_CRITIC_RATING = "critics_ratings";
final String TAG_AUDIENCE_RATING = "audience_ratings";
final String TAG_SYNOPSIS = "synopsis";
final String TAG_POSTERS = "posters";
JSONArray upcomings = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upcoming_list);
ArrayList<HashMap<String, String>> UpcomingList = new ArrayList<HashMap<String, String>>();
// Creating JSON Parser instance
JSONParser jParser = new JSONParser();
// getting JSON string from URL
JSONObject json = jParser.getJSONFromUrl(url);
try {
// Getting Array of Contacts
upcomings = json.getJSONArray(TAG_MOVIES);
// looping through All Contacts
for(int i = 0; i < upcomings.length(); i++){
JSONObject c = upcomings.getJSONObject(i);
// Storing each json item in variable
String id = c.getString(TAG_ID);
String title = c.getString(TAG_TITLE);
String year = c.getString(TAG_YEAR);
String mpaa_rating = c.getString(TAG_MPAA_RATING);
String runtime = c.getString(TAG_RUNTIME);
JSONObject release_dates = c.getJSONObject(TAG_RELEASE_DATES);
JSONObject ratings = c.getJSONObject(TAG_RATINGS);
String critic_rating = c.getString(TAG_CRITIC_RATING);
String audience_rating = c.getString(TAG_AUDIENCE_RATING);
String synopsis = c.getString(TAG_SYNOPSIS);
JSONObject posters = c.getJSONObject(TAG_POSTERS);
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_TITLE, title);
map.put(TAG_YEAR, year);
map.put(TAG_CRITIC_RATING, critic_rating);
map.put(TAG_AUDIENCE_RATING, audience_rating);
UpcomingList.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
ListAdapter adapter = new SimpleAdapter(this, UpcomingList,
R.layout.activity_upcoming,
new String[] { TAG_TITLE, TAG_YEAR, TAG_CRITIC_RATING, TAG_AUDIENCE_RATING }, new int[]
{
R.id.title, R.id.year, R.id.critic_rating, R.id.audience_rating });
setListAdapter(adapter);
// selecting single ListView item
ListView lv = getListView();
// Launching new screen on Selecting Single ListItem
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// getting values from selected ListItem
String name = ((TextView) view.findViewById(R.id.title)).getText().toString();
String cost = ((TextView) view.findViewById(R.id.year)).getText().toString();
String critic_rating = ((TextView) view.findViewById(R.id.critic_rating)).getText().toString();
String audience_rating = ((TextView) view.findViewById(R.id.audience_rating)).getText().toString();
// Starting new intent
Intent in = new Intent(getApplicationContext(), Upcoming.class);
in.putExtra(TAG_TITLE, name);
in.putExtra(TAG_YEAR, cost);
in.putExtra(TAG_CRITIC_RATING, critic_rating);
in.putExtra(TAG_AUDIENCE_RATING, audience_rating);
startActivity(in);
}
});
}
}
答案 0 :(得分:2)
不要在主线程(UI线程)中使用网络连接使用Asynctask或线程来做。
答案 1 :(得分:1)
使用 AsyncTask
例如: -
class YourTask extends AsyncTask<URL, Integer, String> {
protected String doInBackground(URL... urls) {
// Fetch Data (Task A)
return "Result";
}
protected void onProgressUpdate(Integer... progress) {
// Show progress
}
protected void onPostExecute(String result) {
// Show UI after complete (Task B)
}
}
或
使用以下代码在onCreate()方法中添加以下代码以禁用严格模式:
这不是解决方案,但避免主线程上的网络IO 所以我建议 AsyncTask
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}
答案 2 :(得分:0)
请将您的互联网连接过程代码放入 ASyncTask 或其他线程中。由于ICS和Jelly Bean不允许您在主线程上进行互联网处理。
答案 3 :(得分:0)
您正在主UI线程中解析。这就是为什么它会抛出错误..你应该使用runOnUiThread或AsycTask。
JSONObject json = jParser.getJSONFromUrl(url);
如下所示:
loadingDialog = ProgressDialog.show(youractivity.this, "", "Loading...", true, false);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
runOnUiThread(new Runnable() {
public void run() {
loadingDialog.dismiss();
JSONObject json = jParser.getJSONFromUrl(url);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
答案 4 :(得分:0)
不要在UI /主线程上执行您的http请求 - 您的同步http被阻止,这样做会阻止屏幕上的实际绘制和布局传递。
为响应UI事件而做的http,就像你在Android中尝试这样做一样,他们发明了一个名为AsyncTask的神奇助手。
使用对封闭的Activity类的内部引用创建此类的匿名实例(即,实际上,在活动中定义类并且不要使其成为静态类。)
来自上述文档:
执行异步任务时,任务将完成......
doInBackground(Params ...),在onPreExecute()完成执行后立即在后台线程上调用。此步骤用于执行可能需要很长时间的后台计算。 ...
onPostExecute(Result),在后台计算完成后在UI线程上调用。后台计算的结果作为参数传递给此步骤。
[我已经省略了额外的细节,也是我的重点]。
您的适配器应该引用异步任务,该任务将信息从在UI线程中执行了所有同步http请求的代码块传递到UI线程上可用于触摸其视图的代码块(你在这里更新你的列表视图。)
最佳,
汤姆。