问题
In my application I use JSON
webservice to get data from Google Navigation api
. I use the code is below.
I got the following exception
android.os.NetworkOnMainThreadException
.
How to use AsyncTask? here is my code. Thanks.`public class MainActivity extends MapActivity {
MapView mapView ;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("*************1**************1");
setContentView(R.layout.activity_main);
System.out.println("*************2**************");
mapView = (MapView) findViewById(R.id.mapv);
System.out.println("*************3**************");
Route route = directions(new GeoPoint((int)(26.2*1E6),(int)(50.6*1E6)), new GeoPoint((int)(26.3*1E6),(int)(50.7*1E6)));
RouteOverlay routeOverlay = new RouteOverlay(route, Color.BLUE);
mapView.getOverlays().add(routeOverlay);
mapView.invalidate();
System.out.println("*************4**************");
}
@SuppressLint("ParserError")
private Route directions(final GeoPoint start, final GeoPoint dest) {
//https://developers.google.com/maps/documentation/directions/#JSON <- get api
String jsonURL = "http://maps.googleapis.com/maps/api/directions/json?";
final StringBuffer sBuf = new StringBuffer(jsonURL);
sBuf.append("origin=");
sBuf.append(start.getLatitudeE6()/1E6);
sBuf.append(',');
sBuf.append(start.getLongitudeE6()/1E6);
sBuf.append("&destination=");
sBuf.append(dest.getLatitudeE6()/1E6);
sBuf.append(',');
sBuf.append(dest.getLongitudeE6()/1E6);
sBuf.append("&sensor=true&mode=driving");
Parser parser = new GoogleParser(sBuf.toString());
Route r = parser.parse();
System.out.println("********r in thread*****" +r);
return r;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
} `
回答1:
@imran khan idea of using another thread is the right one. From HoneyComb and above, you can't do any networking operation inside the UI Thread. The UI Thread is the thread responsible for displaying views and receiving touch events and it must be free for this, not blocked by a long running operation. (Otherwise you got an ANR on Android).
But it's actually not a very good idea to use an AsyncTask for long running operations like a network Request. The AsyncTask javadocs even states they have been designed for short runnning operations...
The best approach is to use a service for that. I encourage you to read this infographics from the RoboSpice library and use RoboSpice, it will ease creating a service with networking and will make it easier for your to parse your json content using Spring Android.
回答2:
You can put your code for getting the data using webservice in the doInBackground() method of AsyncTask class and return that result from that function. It will get in the onPostExecute() method and there you can parse and update your UI.
private class myasyncclass extends AsyncTask<String, Void, Route>{
@Override
protected Route doInBackground(String... params) {
//Enter code for fetching data from remote server using webservice
return yourRoutevalue;
}
@Override
protected void onPostExecute(Route result) {
//Enter code for parsing and using the data(Update UI)
}
}
You should have same type in AsyncTask(DoInBackground, Progress, OnPostExecute)
回答3:
Change your Code as using AsyncTask:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your Code here
new LongOperation().execute("");
System.out.println("*************4**************");
}
private class LongOperation extends AsyncTask<String, Void, String> {
@Override
protected Route doInBackground(String... params) {
Route route;
try {
route = directions(new GeoPoint((int)(26.2*1E6),
(int)(50.6*1E6)), new GeoPoint((int)(26.3*1E6),(int)(50.7*1E6)));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Route ;
}
@Override
protected void onPostExecute(Route route) {
// Update Ui here
RouteOverlay routeOverlay = new RouteOverlay(route, Color.BLUE);
mapView.getOverlays().add(routeOverlay);
mapView.invalidate();
}
}
NOTE : if you are passing any value from UI elements to HTTP REQUEST then you must pass it as parameters to AsyncTask's doInBackground method. you can see how we pass parameter to AsyncTask here:
http://developer.android.com/reference/android/os/AsyncTask.html
来源:https://stackoverflow.com/questions/13667152/how-to-use-method-in-asynctask-in-android