0

I have a MyMapActivity with private class extending AsyncTask for purpose to do request on server every time when map section is changed (onMove() method). Response from server is JSON data string which could be about 1-3 MB. So I need to avoid multiple calls to server when user is moving the map to avoid OutOfMemory. For that reason I'm trying to check if my own AsyncTask is cancelled (on every onMove() start) and if not(I suppose that indicates about performing doInBackground() method) I'm tying to cancel it. But regardless of this I still have a

01-19 20:45:05.660: ERROR/MapActivity(2482): Couldn't get connection factory client
01-19 20:45:40.600: ERROR/Tethering(96): active iface (usb0) reported as added, ignoring
01-19 20:47:15.260: ERROR/dalvikvm-heap(2482): Out of memory on a 11908-byte allocation.
01-19 20:47:15.270: ERROR/dalvikvm(2482): Out of memory: Heap Size=24519KB, Allocated=23091KB, Bitmap Size=101KB
01-19 20:47:15.410: ERROR/dalvikvm-heap(2482): Out of memory on a 7690-byte allocation.
01-19 20:47:15.420: ERROR/dalvikvm(2482): Out of memory: Heap Size=24519KB, Allocated=23088KB, Bitmap Size=101KB
01-19 20:47:15.570: ERROR/dalvikvm-heap(2482): Out of memory on a 7656-byte allocation.
01-19 20:47:15.590: ERROR/dalvikvm(2482): Out of memory: Heap Size=24519KB, Allocated=23090KB, Bitmap Size=101KB
01-19 20:47:15.730: ERROR/dalvikvm-heap(2482): Out of memory on a 9098-byte allocation.
01-19 20:47:15.740: ERROR/dalvikvm(2482): Out of memory: Heap Size=24519KB, Allocated=23097KB, Bitmap Size=101KB
01-19 20:48:01.850: ERROR/dalvikvm-heap(2482): Out of memory on a 8176-byte allocation.
01-19 20:48:01.850: ERROR/dalvikvm(2482): Out of memory: Heap Size=24519KB, Allocated=22767KB, Bitmap Size=101KB
01-19 20:48:01.970: ERROR/dalvikvm-heap(2482): Out of memory on a 12022-byte allocation.
01-19 20:48:01.980: ERROR/dalvikvm(2482): Out of memory: Heap Size=24519KB, Allocated=22768KB, Bitmap Size=101KB
01-19 20:48:02.110: ERROR/dalvikvm-heap(2482): Out of memory on a 8936-byte allocation.
01-19 20:48:02.119: ERROR/dalvikvm(2482): Out of memory: Heap Size=24519KB, Allocated=22769KB, Bitmap Size=101KB
01-19 20:48:07.220: WARN/dalvikvm(2482): threadid=20: thread exiting with uncaught exception (group=0x400259f8)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482): FATAL EXCEPTION: AsyncTask #9
01-19 20:48:07.350: ERROR/AndroidRuntime(2482): java.lang.RuntimeException: An error occured while executing doInBackground()
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at android.os.AsyncTask$3.done(AsyncTask.java:200)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at java.lang.Thread.run(Thread.java:1102)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482): Caused by: java.lang.OutOfMemoryError
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at java.lang.String.(String.java:468)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at java.lang.AbstractStringBuilder.toString(AbstractStringBuilder.java:659)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at java.lang.StringBuilder.toString(StringBuilder.java:664)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.stream.JsonReader.nextString(JsonReader.java:995)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.stream.JsonReader.nextValue(JsonReader.java:810)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.stream.JsonReader.objectValue(JsonReader.java:790)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.stream.JsonReader.quickPeek(JsonReader.java:385)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.stream.JsonReader.peek(JsonReader.java:348)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.internal.bind.TypeAdapters$12.read(TypeAdapters.java:322)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.internal.bind.TypeAdapters$12.read(TypeAdapters.java:334)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:86)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:170)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:38)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.internal.bind.ArrayTypeAdapter.read(ArrayTypeAdapter.java:71)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:86)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:170)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.Gson.fromJson(Gson.java:720)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at com.google.gson.Gson.fromJson(Gson.java:660)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at net.amagumo.realestate.MyMapActivity$MyTask.getHttpContent(MyMapActivity.java:444)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at net.amagumo.realestate.MyMapActivity$MyTask.doInBackground(MyMapActivity.java:393)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at net.amagumo.realestate.MyMapActivity$MyTask.doInBackground(MyMapActivity.java:1)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-19 20:48:07.350: ERROR/AndroidRuntime(2482):     ... 4 more
01-19 20:48:07.450: WARN/ActivityManager(96):   Force finishing activity net.amagumo.realestate/.MyMapActivity
01-19 20:48:21.290: WARN/TimeThread(294): conver time failed
01-19 20:48:42.899: WARN/TimeThread(294): conver time failed 

Here is my activity class:

public class MyMapActivity extends MapActivity implements LocationListener, OnTouchListener, OnMoveListener, MyMapItemClickedListener, DefaultActivity {

    MyMapView  mv;
    MapController mc;
    LocationManager lm;
    MyItemizedOverlay myOverlay;
    DatabaseAdapter db;
    AdvertResult advertResult;
    String callerActivityString;

    MyTask mytask;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Log.d(Constants.DEBUG_TAG, "MAP - create");
        setContentView(R.layout.map);

        db = new DatabaseAdapter(getApplicationContext()).open();
        mv = (MyMapView)this.findViewById(R.id.mapView);
        mc = mv.getController();
        lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

        mv.setOnTouchListener(this);
        mv.setmOnMoveListener(this);

        mv.setSatellite(true);

        Drawable marker=getResources().getDrawable(R.drawable.ic_maps_indicator_startpoint_list);

        int markerWidth = marker.getIntrinsicWidth();
        int markerHeight = marker.getIntrinsicHeight();
        marker.setBounds(0, markerHeight, markerWidth, 0);

        myOverlay = new MyItemizedOverlay(marker);
        myOverlay.setMyMapItemClickedListener(this);

        mv.getOverlays().add(myOverlay);

        advertResult = new AdvertResult();

        mytask = new MyTask();


    }


    public void completeMap(){
        Log.d(Constants.DEBUG_TAG_MAPS, "completing map - START");
        for(AdvertSimple is : advertResult.getAdvertSimpleList()){
            if(is.getAdress().getLat()!=null && is.getAdress().getLon()!=null){
                GeoPoint gp = new GeoPoint(is.getAdress().getLat(), is.getAdress().getLon());
                myOverlay.addItem(gp, "Advert", "snippet");
            }
        }
        Log.d(Constants.DEBUG_TAG_MAPS, "completing map - END");
    }

    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }

    public void onLocationChanged(Location loc) {
    }

    public void onProviderDisabled(String provider) {
    }

    public void onProviderEnabled(String provider) {
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

    public boolean onTouch(View v, MotionEvent event) {
        return false;
    }

    public void onMove(MapView mapView, GeoPoint center, boolean stopped) {

        if(!mytask.isCancelled()){
            Log.d(Constants.DEBUG_TAG_MAPS, "async task is cancelling - ATTEMPT");
            mytask.cancel(true);
            System.gc();
        }
        if(stopped){

            Log.d(Constants.DEBUG_TAG_MAPS, "finished move/zoom action");

            Integer latspan  = mv.getLatitudeSpan();
            Integer lonspan  = mv.getLongitudeSpan();

            Integer maxlat = center.getLatitudeE6() + (latspan/2);
            Integer maxlon = center.getLongitudeE6() + (lonspan/2);
            Integer minlat = center.getLatitudeE6() - (latspan/2);
            Integer minlon = center.getLongitudeE6() - (lonspan/2);

            mytask = new MyTask();
            mytask.execute(this, null, new ResultComposite());

        }
    }

    public MapRectangle getRectangle(){

        GeoPoint center = mv.getMapCenter();

        Integer latspan  = mv.getLatitudeSpan();
        Integer lonspan  = mv.getLongitudeSpan();
        Integer maxlat = center.getLatitudeE6() + (latspan/2);
        Integer maxlon = center.getLongitudeE6() + (lonspan/2);
        Integer minlat = center.getLatitudeE6() - (latspan/2);
        Integer minlon = center.getLongitudeE6() - (lonspan/2);

        return new MapRectangle(maxlat, maxlon, minlat, minlon);
    }


    @Override
    public void completeAction(ResultComposite result) {
        Log.d(Constants.DEBUG_TAG_MAPS, "async tasc is going to complete in caller activity - OK");     
        if(result!=null){
            advertResult.setAdvertSimpleList(result.getAdvertSimpleList());
            completeMap();  
        }


    }
    @Override
    public RequestParams getRequestParams() {
        RequestParams params = new RequestParams();
        params.setDb(db);
        params.setRectangle(getRectangle());
        return params;
    }   

    private class MyTask extends AsyncTask{

        public MyMapActivity ma;
        public HttpClient httpclient;

        @Override
        protected ResultComposite doInBackground(Object... params) {

            Log.d(Constants.DEBUG_TAG_MAPS, "async tasc do in backgrounf - START");
            ma = (MyMapActivity) params[0];
            ResultComposite rc = new ResultComposite();
            RequestParams rp = ma.getRequestParams();

            MapRectangle rectangle = rp.getRectangle();

            RequestJSONObject ro = new RequestJSONObject(rectangle.getMinlat(), rectangle.getMinlon(), rectangle.getMaxlat(), rectangle.getMaxlon());
            Gson gson = new Gson();
            String json = gson.toJson(ro);
            ResponseJSONObject responseJSONObject = getHttpContent(json, Constants.HTTP_REQUEST_MAP);
            AdvertSimpleJSON[] AdvertSimpleJSONarray = responseJSONObject.getAdvertySimple();

            List simples = DataHelper.convertAdvertSimpleJSONArray2AdvertSimpleList(rp.getDb(),  AdvertSimpleJSONarray);

            rc.setAdvertSimpleList(simples);

            return rc;

        }

        @Override
        protected void onPostExecute(ResultComposite result) {
            super.onPostExecute(result);
            Log.d(Constants.DEBUG_TAG_MAPS, "async tasc is going to complete in caller activity - ATTEMPT");
            ma.completeAction(result);

        }



        @Override
        protected void onCancelled() {
            super.onCancelled();
            Log.d(Constants.DEBUG_TAG_MAPS, "async task is cancelling - OK");
        }

        private ResponseJSONObject getHttpContent(String json, String requestType){

            ResponseJSONObject responseJSONObject = null;
            HttpPost post = new HttpPost(Constants.SERVER_MAP_URL);
            try {
                Log.d(Constants.DEBUG_TAG_MAPS, "try");

                HttpEntity entity = new StringEntity(json);
                post.setEntity(entity);

                HttpParams httpParameters = new BasicHttpParams();
                HttpConnectionParams.setConnectionTimeout(httpParameters, 15000);
                HttpConnectionParams.setSoTimeout(httpParameters, 150000);

                httpclient  = new DefaultHttpClient(httpParameters);

                BasicHttpResponse  response = (BasicHttpResponse ) httpclient.execute(post);
                if(response.getStatusLine().getStatusCode() == 200){
                    Log.d(Constants.DEBUG_TAG, "response 200");
                    HttpEntity responseEntity = response.getEntity();
                    Gson g = new Gson();
                    BufferedReader reader = new BufferedReader ( new InputStreamReader ( responseEntity.getContent()) );
                    responseJSONObject = g.fromJson(reader, ResponseJSONObject.class);
                    reader.close();
                    System.gc();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            Log.d(Constants.DEBUG_TAG_MAPS, "returning http results");

            return responseJSONObject;
        } 



    }
}


What else should I do? I have tried to perform consume http entity.

Is my logic with handling AsynTask correct?

falconseye
  • 187
  • 2
  • 5
  • 16
  • It is better to segregate or look for alternatvies. Really you can't have large data cached because of limited access of memory per process. – kosa Jan 19 '12 at 20:14
  • yes he can, but not in memory ... he should use sqlite and ... well, pull parser(Jackson) not gson – Selvin Jan 19 '12 at 20:22
  • I understand but I have no problem with same size set of data when I handle with ListActivity in which call to server is done one time. Problem is that asynctask and I think not functional work of my AsyncTask and cancelling. – falconseye Jan 19 '12 at 20:24
  • Selvin is some crucial different between Jackson and Gson? Something could affect memory? – falconseye Jan 19 '12 at 20:27
  • i'll go for ContentProvider ... like i did in my project http://selvinlistsyncsample.codeplex.com/SourceControl/changeset/view/40943209facc – Selvin Jan 19 '12 at 20:29
  • just save whole response and check how big is it ... – Selvin Jan 19 '12 at 20:30

0 Answers0