开发者

Properly dealing with network on main thread connection in drawing overlays on map for android tablet

After playing with honeycomb a lot, it turns out if you do any HTTP stuff it wines about a NetworkOnMainThread issue. I was dealing with this by putting my calls to http in a separate AsynTask and this seemed to work well...

Now I am trying to load a WMS layer im fetching (Via https) and put it开发者_运维知识库 on the map. This is working okay but my way of using AsyncTask isn't cutting it as everytime the draw was called on the overlay (which I think is everytime you move the map) it was doing another

new getWmsAsync().execute();

which means after a while there was max threads.

I am not sure what the right fix for this is. Or how to engineer this in the correct way after doing it the way I knew how failed me. What pieces am I missing? Is there away to get the https request on a different thread (it has to be done every time the map is moved I think).

The original calls:

in the WMSOverlay extends Overlay class:

@Override
  public void draw(Canvas canvas, MapView mapView,
           boolean shadow) {
   super.draw(canvas, mapView, shadow);
   mCanvas=canvas;
   wmsclient = new WMSLoader(mapView.getContext());
   cornerCoords = MapUtils.getCornerCoordinates(mapView.getProjection(), canvas);

   //new getWmsAsync().execute();
   Paint semitransparent = new Paint();
   semitransparent.setAlpha(0x888);
   mCanvas.drawBitmap( , 0, 0, semitransparent);

  }

But my wsmClient.loadMap has http calls in it so it dies with the above NetworkOnMainThread. My fix was this:

@Override
  public void draw(Canvas canvas, MapView mapView,
           boolean shadow) {
   super.draw(canvas, mapView, shadow);
   mCanvas=canvas;
   wmsclient = new WMSLoader(mapView.getContext());
   cornerCoords = MapUtils.getCornerCoordinates(mapView.getProjection(), canvas);

   new getWmsAsync().execute(); //too many threads here...

  }

private class getWmsAsync extends AsyncTask<Void, Void, Bitmap>{
    @Override
     protected void onPostExecute(Bitmap image) {
           Paint semitransparent = new Paint();
           semitransparent.setAlpha(0x888);
           mCanvas.drawBitmap(image, 0, 0, semitransparent);
           this.cancel(true);              
        }
    @Override
    protected Bitmap doInBackground(Void... params) {
        // TODO Auto-generated method stub
        return wmsclient.loadMap(mCanvas.getWidth(), mCanvas.getHeight(), cornerCoords[0], cornerCoords[1], null);
    }         
}

if I use that way with the .execute() i end up with this error:

08-23 17:01:05.520: ERROR/AndroidRuntime(5436): java.util.concurrent.RejectedExecutionException: Task android.os.AsyncTask$3@41147c88 rejected from java.util.concurrent.ThreadPoolExecutor@40880c00[Running, pool size = 128, active threads = 127, queued tasks = 10, completed tasks = 59]


After playing with honeycomb a lot, it turns out if you do any HTTP stuff it wines about a NetworkOnMainThread issue.

AFAIK, you should only get messages if you are using StrictMode. Regardless, more important than the LogCat messages is that you are freezing your UI if you do network I/O on the main application thread.

I am not sure what the right fix for this is.

Well, typically, you cache your HTTP request results, so you do not need to re-request them.

Or, if each of your requests would be for different data, wait until the user pauses, then do a single request for the end result, the same way Google Maps does it for its own map tiles.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜