Правильно работать с сетью на основном потоке связи при рисовании оверлеев на карте для андроид планшета - PullRequest
1 голос
/ 23 августа 2011

После долгой игры с сотами выясняется, что если вы делаете какие-либо HTTP-вещи, то это связано с проблемой NetworkOnMainThread.Я имел дело с этим, помещая мои вызовы в http в отдельную AsynTask, и это, казалось, работало хорошо ...

Теперь я пытаюсь загрузить слой WMS, который я получаю (через https), и поместить его накарта.Это работает нормально, но мой способ использования AsyncTask не обрезает его, так как каждый раз, когда в оверлее вызывается отрисовка (я думаю, это каждый раз, когда вы перемещаете карту), он делал еще один

new getWmsAsync().execute();

, что означаетчерез некоторое время появилось макс потоков.

Я не уверен, что это правильное решение.Или как правильно спроектировать это после того, как я понял, как подвел меня.Какие части я пропускаю?Можно ли получить запрос https в другом потоке (думаю, это нужно делать при каждом перемещении карты).

Исходные вызовы:

в классе WMSOverlay extends Overlay:

@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);

  }

Но у моего wsmClient.loadMap есть http-вызовы, поэтому он умирает с указанным выше NetworkOnMainThread.Мое исправление было таким:

@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);
    }         
}

, если я использую этот способ с .execute(), я получаю эту ошибку:

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]

1 Ответ

1 голос
/ 23 августа 2011

После долгой игры с сотами выясняется, что если вы выполняете какие-либо действия HTTP, связанные с проблемой NetworkOnMainThread.

AFAIK, вы должны получать сообщения, только если используете StrictMode.В любом случае, более важным, чем сообщения LogCat, является то, что вы замораживаете свой пользовательский интерфейс, если выполняете сетевой ввод-вывод в главном потоке приложения.

Я не уверен, что это правильное решение.

Обычно вы кешируете результаты HTTP-запроса, поэтому вам не нужно повторно запрашивать их.

Или, если каждый из ваших запросов будет относиться к разным данным, подождитепока пользователь не сделает паузу, выполните один запрос на конечный результат, так же, как Google Maps делает это для собственных плиток карты.

...