我正在制作一个使用互联网检索信息的应用程序。当我尝试在 3.0 及更高版本上运行它时,我得到了一个NetworkOnMainThreadException
,因此尝试使用 AsyncTask 进行设置,但它仍然给出异常,我不知道出了什么问题。奇怪的是,我在AsyncTask 内部的这个线程 Android NetworkOnMainThreadException上读到,如果您只是android:targetSdkVersion="10"
从清单文件中删除该语句,它将能够运行。这可行,但我认为它不是以这种方式解决问题的正确解决方案。
因此,如果有人能告诉我我在 AsyncTask 上做错了什么,我将不胜感激。此外,如果有人知道为什么删除清单中的语句使其起作用,我也对此很感兴趣。
我的代码如下所示:编辑:更新的代码。
public class MainActivity extends Activity {
static ArrayList<Tumblr> tumblrs;
ListView listView;
TextView footer;
int offset = 0;
ProgressDialog pDialog;
View v;
String responseBody = null;
HttpResponse r;
HttpEntity e;
String searchUrl;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
final ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo();
if (activeNetwork != null && activeNetwork.isConnected()) {
setContentView(R.layout.main);
try {
tumblrs = getTumblrs();
listView = (ListView) findViewById(R.id.list);
View v = getLayoutInflater().inflate(R.layout.footer_layout,
null);
footer = (TextView) v.findViewById(R.id.tvFoot);
listView.addFooterView(v);
listView.setAdapter(new UserItemAdapter(this, R.layout.listitem));
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
new GetChicks().execute();
footer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new loadMoreListView().execute();
}
});
} else {
setContentView(R.layout.nonet);
}
}
public class UserItemAdapter extends ArrayAdapter<Tumblr> {
public UserItemAdapter(Context context, int imageViewResourceId) {
super(context, imageViewResourceId, tumblrs);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.listitem, null);
}
Tumblr tumblr = tumblrs.get(position);
if (tumblr != null) {
ImageView image = (ImageView) v.findViewById(R.id.avatar);
if (image != null) {
image.setImageBitmap(getBitmap(tumblr.image_url));
}
}
return v;
}
}
public Bitmap getBitmap(String bitmapUrl) {
try {
URL url = new URL(bitmapUrl);
return BitmapFactory.decodeStream(url.openConnection()
.getInputStream());
} catch (Exception ex) {
return null;
}
}
public ArrayList<Tumblr> getTumblrs() throws ClientProtocolException,
IOException, JSONException {
searchUrl = "http://api.tumblr.com/v2/blog/factsandchicks.com/posts?api_key=rTZsymOWtMudbb5tql2U20qQ5ooYLPYVNnL3COPpO2qBHDxJUu&limit=2&offset=0";
ArrayList<Tumblr> tumblrs = new ArrayList<Tumblr>();
return tumblrs;
}
private class GetChicks extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... unused) {
// TODO Auto-generated method stub
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(searchUrl);
HttpResponse r = null;
try {
r = client.execute(get);
int status = r.getStatusLine().getStatusCode();
if (status == 200) {
e = r.getEntity();
responseBody = EntityUtils.toString(e);
}
} catch (ClientProtocolException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
JSONObject jsonObject;
try {
jsonObject = new JSONObject(responseBody);
JSONArray posts = jsonObject.getJSONObject("response")
.getJSONArray("posts");
for (int i = 0; i < posts.length(); i++) {
JSONArray photos = posts.getJSONObject(i)
.getJSONArray("photos");
for (int j = 0; j < photos.length(); j++) {
JSONObject photo = photos.getJSONObject(j);
String url = photo.getJSONArray("alt_sizes")
.getJSONObject(0).getString("url");
Tumblr tumblr = new Tumblr(url);
tumblrs.add(tumblr);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
public class Tumblr {
public String image_url;
public Tumblr(String url) {
this.image_url = url;
}
}
private class loadMoreListView extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
// Showing progress dialog before sending http request
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("More chicks coming up..");
pDialog.setIndeterminate(true);
pDialog.setCancelable(false);
pDialog.show();
}
@Override
protected Void doInBackground(Void... unused) {
// TODO Auto-generated method stub
// increment current page
offset += 2;
// Next page request
tumblrs.clear();
String searchUrl = "http://api.tumblr.com/v2/blog/factsandchicks.com/posts?api_key=rTZsymOWtMudbb5tql2U20qQ5ooYLPYVNnL3COPpO2qBHDxJUu&limit=2&offset="
+ offset;
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(searchUrl);
HttpResponse r = null;
try {
r = client.execute(get);
int status = r.getStatusLine().getStatusCode();
if (status == 200) {
HttpEntity e = r.getEntity();
responseBody = EntityUtils.toString(e);
}
} catch (ClientProtocolException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
JSONObject jsonObject;
try {
jsonObject = new JSONObject(responseBody);
JSONArray posts = jsonObject.getJSONObject("response")
.getJSONArray("posts");
for (int i = 0; i < posts.length(); i++) {
JSONArray photos = posts.getJSONObject(i)
.getJSONArray("photos");
for (int j = 0; j < photos.length(); j++) {
JSONObject photo = photos.getJSONObject(j);
String url = photo.getJSONArray("alt_sizes")
.getJSONObject(0).getString("url");
Tumblr tumblr = new Tumblr(url);
tumblrs.add(tumblr);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Setting new scroll position
listView.setSelectionFromTop(0, 0);
return null;
}
protected void onPostExecute(Void unused) {
pDialog.dismiss();
}
}
@Override
public boolean onCreateOptionsMenu(android.view.Menu menu) {
// TODO Auto-generated method stub
super.onCreateOptionsMenu(menu);
MenuInflater blowUp = getMenuInflater();
blowUp.inflate(R.menu.cool_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.aboutUs:
Intent i = new Intent("com.example.example.ABOUT");
startActivity(i);
break;
case R.id.refresh:
Intent f = new Intent(MainActivity.this, MainActivity.class);
startActivity(f);
finish();
break;
case R.id.exit:
finish();
break;
}
return false;
}
}
日志如下所示:
10-07 10:27:56.163: E/AndroidRuntime(923): FATAL EXCEPTION: AsyncTask #2
10-07 10:27:56.163: E/AndroidRuntime(923): java.lang.RuntimeException: An error occured while executing doInBackground()
10-07 10:27:56.163: E/AndroidRuntime(923): at android.os.AsyncTask$3.done(AsyncTask.java:278)
10-07 10:27:56.163: E/AndroidRuntime(923): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
10-07 10:27:56.163: E/AndroidRuntime(923): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
10-07 10:27:56.163: E/AndroidRuntime(923): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
10-07 10:27:56.163: E/AndroidRuntime(923): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
10-07 10:27:56.163: E/AndroidRuntime(923): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
10-07 10:27:56.163: E/AndroidRuntime(923): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
10-07 10:27:56.163: E/AndroidRuntime(923): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
10-07 10:27:56.163: E/AndroidRuntime(923): at java.lang.Thread.run(Thread.java:856)
10-07 10:27:56.163: E/AndroidRuntime(923): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
10-07 10:27:56.163: E/AndroidRuntime(923): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:3939)
10-07 10:27:56.163: E/AndroidRuntime(923): at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:701)
10-07 10:27:56.163: E/AndroidRuntime(923): at android.view.View.requestLayout(View.java:12555)
10-07 10:27:56.163: E/AndroidRuntime(923): at android.view.View.requestLayout(View.java:12555)
10-07 10:27:56.163: E/AndroidRuntime(923): at android.view.View.requestLayout(View.java:12555)
10-07 10:27:56.163: E/AndroidRuntime(923): at android.view.View.requestLayout(View.java:12555)
10-07 10:27:56.163: E/AndroidRuntime(923): at android.view.View.requestLayout(View.java:12555)
10-07 10:27:56.163: E/AndroidRuntime(923): at android.widget.AbsListView.requestLayout(AbsListView.java:1690)
10-07 10:27:56.163: E/AndroidRuntime(923): at android.widget.ListView.setSelectionFromTop(ListView.java:1928)
10-07 10:27:56.163: E/AndroidRuntime(923): at com.fansheroid.facts.chicks.MainActivity$loadMoreListView.doInBackground(MainActivity.java:291)
10-07 10:27:56.163: E/AndroidRuntime(923): at com.fansheroid.facts.chicks.MainActivity$loadMoreListView.doInBackground(MainActivity.java:1)
10-07 10:27:56.163: E/AndroidRuntime(923): at android.os.AsyncTask$2.call(AsyncTask.java:264)
10-07 10:27:56.163: E/AndroidRuntime(923): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
10-07 10:27:56.163: E/AndroidRuntime(923): ... 5 more