1

I have a view where I draw a tree shaped structure using Canvas and Path and it looks like the one given below. The way I draw the tree is a bad coding habit and I am well aware of it but I had to follow this style due to the lack of better way. (I did not try it in OpenGL, I'm a bit afraid to try that). So the steps that takes place in tree are as follows :

  1. Tree is drawn without using any text in it.
  2. As the users are added to the tree, the leaves color gets changed and text is added to it.
  3. Further to this, these leaves should have images rather than plain text which can be achieved by using drawBitmap which will obviously lead me to OOM (Out Of Memory) in the future.

So these are the steps that happens as of now, this takes me at least 3-4 seconds to load the screen when the colored leaf count is less (meaning that there are less users), if there are more users then the loading time exceeds more than 5 seconds and at times, it shows "App not responding" due to more memory consumption.

I have no idea on how to proceed further because showing this screen to the user takes up all the memory and forces my app to close.

So I am completely stuck at this point unable to proceed further and I have invested a great deal of time building this tree so I hope that there should be way to clear the memory and re-build the canvas.

What have I learned so far : Android does not allow to draw a part of the page again, so the whole canvas has to be regenerated again when the page is loaded.

P.S: If there is a way to overcome the memory issue using the existing code then its highly appreciated cause the time wasted has been too much, if at all there is no other way but to destroy this completely and start from scratch then I hope that way will give me exactly what I want.

Tree : enter image description here

CODE :

 @Override
    public void onDraw(Canvas canv) {



        //gggggggggggg
        for (CircleArea circle : mCircles) {



                if(dbHelper.getRelationTypes().size() > 0)
                {
                    //System.out.println("dbHelper.getRelationTypes().size() > 0");
                    //System.out.println("Inside the Spouse or Father and Mother");
                    CircleCanvas.spouse_added = true;
                    //Couples
                    if(circle.radius==XHDPI_COUPLE_RADIUS_LIMIT)
                    {
                        // System.out.println("if(circle.radius==70)");
                        if(circle.getCenterX() == my_x && circle.getCenterY() == my_y)
                        {
                            dbHelper.insertXYOfRelation("Self", circle.getCenterX(), circle.getCenterY());

                            if(DashboardActivity.profile_image_from_local!=null)
                            {
                                Bitmap resized = Bitmap.createScaledBitmap(DashboardActivity.profile_image_from_local, 200, 200, true);
                                Bitmap result = null;
                                try {
                                    result = Bitmap.createBitmap(200,200, Bitmap.Config.ARGB_8888);
                                    Canvas canvas = new Canvas(result);
                                    int color = 0xff424242;
                                    Paint paint = new Paint();
                                    Rect rect = new Rect(0, 0, 200, 200);
                                    //RectF rectF = new RectF(rect);
                                    paint.setAntiAlias(true);
                                    canvas.drawARGB(0, 0, 0, 0);
                                    paint.setColor(color);
                                    canvas.drawCircle(XHDPI_COUPLE_RADIUS_LIMIT, XHDPI_COUPLE_RADIUS_LIMIT, XHDPI_COUPLE_RADIUS_LIMIT, paint);
                                    //canvas.drawOval(rectF, paint);
                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
                                    canvas.drawBitmap(resized, rect, rect, paint);

                                } catch (NullPointerException e) {
                                } catch (OutOfMemoryError o) {
                                }

                                System.out.println("Inside Me");
                                canv.drawBitmap(result, circle.getCenterX() - result.getWidth() / 3, circle.getCenterY() - result.getHeight() / 3, null);
                            }

                            else  if(DashboardActivity.profile_image!=null)
                            {
                                Bitmap resized = Bitmap.createScaledBitmap(DashboardActivity.profile_image, 200, 200, true);
                                Bitmap result = null;
                                try {
                                    result = Bitmap.createBitmap(200,200, Bitmap.Config.ARGB_8888);
                                    Canvas canvas = new Canvas(result);
                                    int color = 0xff424242;
                                    Paint paint = new Paint();
                                    Rect rect = new Rect(0, 0, 200, 200);
                                    //RectF rectF = new RectF(rect);
                                    paint.setAntiAlias(true);
                                    canvas.drawARGB(0, 0, 0, 0);
                                    paint.setColor(color);
                                    canvas.drawCircle(XHDPI_COUPLE_RADIUS_LIMIT, XHDPI_COUPLE_RADIUS_LIMIT, XHDPI_COUPLE_RADIUS_LIMIT, paint);
                                    //canvas.drawOval(rectF, paint);
                                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
                                    canvas.drawBitmap(resized, rect, rect, paint);

                                } catch (NullPointerException e) {
                                } catch (OutOfMemoryError o) {
                                }

                                System.out.println("Inside Me");
                                canv.drawBitmap(result, circle.getCenterX() - result.getWidth() / 3, circle.getCenterY() - result.getHeight() / 3, null);
                            }
                            else
                            {
                                canv.drawCircle(circle.getCenterX(), circle.getCenterY(), XHDPI_COUPLE_RADIUS_LIMIT, mMarriedPaint);
                                canv.drawText(dbHelper.getNameOfRelation("Self"), circle.getCenterX() - 34, circle.getCenterY(), mXHDPICoupleTextPaint);
                                Log.e("Ondraw Self", "Ondraw Self");
                            }


                        }
                        else
                        {
                            if(dbHelper.getWhatRelationTypes("Spouse"))
                            {
                               // System.out.println("Inside Spouse");
                                dbHelper.insertXYOfRelation("Spouse",circle.getCenterX(),circle.getCenterY());
                                Log.e("Spouseeeeeeee ", "" + circle.getCenterX() + " " + circle.getCenterY() + dbHelper.insertXYOfRelation("Spouse", circle.getCenterX(), circle.getCenterY()));
                                canv.drawCircle(circle.getCenterX(), circle.getCenterY(), XHDPI_COUPLE_RADIUS_LIMIT, mMarriedPaint);
                                canv.drawText(dbHelper.getNameOfRelation("Spouse"), circle.getCenterX() - 34, circle.getCenterY(), mXHDPICoupleTextPaint);
                            }
                            else
                            {
                                canv.drawCircle(circle.getCenterX(), circle.getCenterY(), XHDPI_COUPLE_RADIUS_LIMIT, mFilledPaint);
                                Log.e("Ondraw Spouse", "Ondraw Spouse");
                            }


                        }
                    }

                    //Parents
                    if(circle.radius==XHDPI_PARENTS_RADIUS_LIMIT)
                    {

                       // System.out.println("if(circle.radius==55)");
                        if(circle.getCenterX() == father_x && circle.getCenterY() == father_y)
                        {

                            if(dbHelper.getWhatRelationTypes("Father"))
                            {
                                dbHelper.insertXYOfRelation("Father", circle.getCenterX(), circle.getCenterY());
                              //  System.out.println("Inside Father" + "X : " + dbHelper.getXOfRelation("Father") + " Y: " +dbHelper.getYOfRelation("Father"));
                                    canv.drawCircle(dbHelper.getXOfRelation("Father"),dbHelper.getYOfRelation("Father"), XHDPI_PARENTS_RADIUS_LIMIT, mMarriedPaint);
                                    canv.drawText(dbHelper.getNameOfRelation("Father"), circle.getCenterX() - 22, circle.getCenterY(), mXHDPIParentsTextPaint);
                            }
                            else
                            {
                                canv.drawCircle(circle.getCenterX(), circle.getCenterY(), XHDPI_PARENTS_RADIUS_LIMIT, mFilledPaint);
                                Log.e("Ondraw Father", "Ondraw Father");
                            }
                        }else if(circle.getCenterX() == mother_x && circle.getCenterY() == mother_y)
                        {
                            if(dbHelper.getWhatRelationTypes("Mother"))
                            {
                               // System.out.println("Inside Mother");
                                dbHelper.insertXYOfRelation("Mother", circle.getCenterX(), circle.getCenterY());
                                canv.drawCircle(dbHelper.getXOfRelation("Mother"), dbHelper.getYOfRelation("Mother"), XHDPI_PARENTS_RADIUS_LIMIT, mMarriedPaint);
                                canv.drawText(dbHelper.getNameOfRelation("Mother"), circle.getCenterX() - 22, circle.getCenterY(), mXHDPIParentsTextPaint);
                            }
                            else
                            {
                                canv.drawCircle(circle.getCenterX(), circle.getCenterY(), XHDPI_PARENTS_RADIUS_LIMIT, mFilledPaint);
                                Log.e("Ondraw Mother", "Ondraw Mother");
                            }
                        }else if(circle.getCenterX() == spouse_father_x && circle.getCenterY() == spouse_father_y)
                        {
                            if(dbHelper.getWhatRelationTypes("Spouses Father"))
                            {
                               // System.out.println("Inside Spouses Father");
                                dbHelper.insertXYOfRelation("Spouses Father", circle.getCenterX(), circle.getCenterY());
                                canv.drawCircle(dbHelper.getXOfRelation("Spouses Father"), dbHelper.getYOfRelation("Spouses Father"), XHDPI_PARENTS_RADIUS_LIMIT, mMarriedPaint);
                                canv.drawText(dbHelper.getNameOfRelation("Spouses Father"), circle.getCenterX() - 22, circle.getCenterY(), mXHDPIParentsTextPaint);
                            }
                            else
                            {
                                canv.drawCircle(circle.getCenterX(), circle.getCenterY(), XHDPI_PARENTS_RADIUS_LIMIT, mFilledPaint);
                                Log.e("Ondraw Spouses Father", "Ondraw Spouses Father");
                            }
                        }else if(circle.getCenterX() == spouse_mother_x && circle.getCenterY() == spouse_mother_y)
                        {
                            if(dbHelper.getWhatRelationTypes("Spouses Mother"))
                            {
                                dbHelper.insertXYOfRelation("Spouses Mother", circle.getCenterX(), circle.getCenterY());
                                canv.drawCircle(dbHelper.getXOfRelation("Spouses Mother"), dbHelper.getYOfRelation("Spouses Mother"), XHDPI_PARENTS_RADIUS_LIMIT, mMarriedPaint);
                                canv.drawText(dbHelper.getNameOfRelation("Spouses Mother"), circle.getCenterX() - 22, circle.getCenterY(), mXHDPIParentsTextPaint);
                            }
                            else
                            {
                                canv.drawCircle(circle.getCenterX(), circle.getCenterY(), XHDPI_PARENTS_RADIUS_LIMIT, mFilledPaint);
                                Log.e("Ondraw Spouses Mother", "Ondraw Spouses Mother");
                            }
                        }

                    }



                   //Childrens
                    if (circle.radius == XHDPI_CHILD_RADIUS_LIMIT) {

                        if (dbHelper.FetchChildFriendCountFromUserTable("Child").size() > 0) {

                            child_x.clear();
                            child_y.clear();

                            child_x.add(c1_x);
                            child_x.add(c2_x);
                            child_x.add(c3_x);
                            child_x.add(c4_x);
                            child_x.add(c5_x);

                            child_y.add(c1_y);
                            child_y.add(c2_y);
                            child_y.add(c3_y);
                            child_y.add(c4_y);
                            child_y.add(c5_y);


                            for (int r = 0; r < dbHelper.FetchChildFriendCountFromUserTable("Child").size(); r++) {


                                if(dbHelper.FetchChildFriendCountFromUserTable("Child").get(r).equalsIgnoreCase("Child1"))
                                {

                                    new_c_x = c1_x;
                                    new_c_y = c1_y;

                                    dbHelper.insertChildOriginalXY("Child1", new_c_x, new_c_y);
                                    dbHelper.insertXYOfRelation("Child1", new_c_x, new_c_y);

                                    child_x.remove(new Integer(c1_x));
                                    child_y.remove(new Integer(c1_y));

                                    canv.drawCircle(dbHelper.getXOfRelation("Child1"), dbHelper.getYOfRelation("Child1"), XHDPI_DRAWN_CHILD_RADIUS_LIMIT, mChildFilledPaint);
                                    canv.drawText(dbHelper.getNameOfRelation("Child1"), dbHelper.getXOfRelation("Child1") - 14, dbHelper.getYOfRelation("Child1"), mXHDPIChildTextPaint);

                                }else  if(dbHelper.FetchChildFriendCountFromUserTable("Child").get(r).equalsIgnoreCase("Child2"))
                                {

                                    new_c_x = c2_x;
                                    new_c_y = c2_y;

                                    child_x.remove(new Integer(c2_x));
                                    child_y.remove(new Integer(c2_y));

                                    dbHelper.insertChildOriginalXY("Child2", new_c_x, new_c_y);
                                    dbHelper.insertXYOfRelation("Child2", new_c_x, new_c_y);
                                    canv.drawCircle(dbHelper.getXOfRelation("Child2"), dbHelper.getYOfRelation("Child2"), XHDPI_DRAWN_CHILD_RADIUS_LIMIT, mChildFilledPaint);
                                    canv.drawText(dbHelper.getNameOfRelation("Child2"), dbHelper.getXOfRelation("Child2") - 14, dbHelper.getYOfRelation("Child2"), mXHDPIChildTextPaint);
                                }else   if(dbHelper.FetchChildFriendCountFromUserTable("Child").get(r).equalsIgnoreCase("Child3"))
                                {

                                    new_c_x = c3_x;
                                    new_c_y = c3_y;


                                    child_x.remove(new Integer(c3_x));
                                    child_y.remove(new Integer(c3_y));


                                    dbHelper.insertChildOriginalXY("Child3", new_c_x, new_c_y);
                                    dbHelper.insertXYOfRelation("Child3", new_c_x, new_c_y);
                                    canv.drawCircle(dbHelper.getXOfRelation("Child3"), dbHelper.getYOfRelation("Child3"), XHDPI_DRAWN_CHILD_RADIUS_LIMIT, mChildFilledPaint);
                                    canv.drawText(dbHelper.getNameOfRelation("Child3"), dbHelper.getXOfRelation("Child3") - 14, dbHelper.getYOfRelation("Child3"), mXHDPIChildTextPaint);
                                }else   if(dbHelper.FetchChildFriendCountFromUserTable("Child").get(r).equalsIgnoreCase("Child4"))
                                {

                                    new_c_x = c4_x;
                                    new_c_y = c4_y;


                                    child_x.remove(new Integer(c4_x));
                                    child_y.remove(new Integer(c4_y));


                                    dbHelper.insertChildOriginalXY("Child4", new_c_x, new_c_y);
                                    dbHelper.insertXYOfRelation("Child4", new_c_x, new_c_y);
                                    canv.drawCircle(dbHelper.getXOfRelation("Child4"), dbHelper.getYOfRelation("Child4"), XHDPI_DRAWN_CHILD_RADIUS_LIMIT, mChildFilledPaint);
                                    canv.drawText(dbHelper.getNameOfRelation("Child4"), dbHelper.getXOfRelation("Child4") - 14, dbHelper.getYOfRelation("Child4"), mXHDPIChildTextPaint);
                                }else  if(dbHelper.FetchChildFriendCountFromUserTable("Child").get(r).equalsIgnoreCase("Child5"))
                                {

                                    new_c_x = c5_x;
                                    new_c_y = c5_y;


                                    child_x.remove(new Integer(c5_x));
                                    child_y.remove(new Integer(c5_y));

                                    dbHelper.insertChildOriginalXY("Child5", new_c_x, new_c_y);
                                    dbHelper.insertXYOfRelation("Child5", new_c_x, new_c_y);
                                    canv.drawCircle(dbHelper.getXOfRelation("Child5"), dbHelper.getYOfRelation("Child5"), XHDPI_DRAWN_CHILD_RADIUS_LIMIT, mChildFilledPaint);
                                    canv.drawText(dbHelper.getNameOfRelation("Child5"), dbHelper.getXOfRelation("Child5") - 14, dbHelper.getYOfRelation("Child5"), mXHDPIChildTextPaint);
                                }


                            }
                            if(child_x.size()!=0)
                            {
                                for(int i=0;i<child_x.size();i++)
                                {
                                    canv.drawCircle(child_x.get(i),child_y.get(i),XHDPI_CHILD_RADIUS_LIMIT,mCirclePaint);
                                }

                            }


                        } else {

                            canv.drawCircle(circle.getCenterX(), circle.getCenterY(), XHDPI_CHILD_RADIUS_LIMIT, mCirclePaint);

                        }
                    }

                    //Friends
                    if (circle.radius==FRIENDS_RADIUS_LIMIT)
                    {
                        //tujomila
                        if(dbHelper.FetchChildFriendCountFromUserTable("Friend").size() > 0)
                        {

                           // Log.e("","The friend list size is " + dbHelper.getFriendRelationTypes().size());
                           // Log.e("","The size of circlepointers is " + circle_pointers);

                            for (int q=1;q<=dbHelper.FetchChildFriendCountFromUserTable("Friend").size();q++)
                            {
                                //Log.e("","The X of friend" + q + " is " + dbHelper.getFriendCorrespondingXValue(q,"Married")) ;
                                //Log.e("","The Y of friend" + q + " is " + dbHelper.getFriendCorrespondingYValue(q,"Married")) ;

                                canv.drawCircle(dbHelper.getFriendCorrespondingXValue(q,"Married"),dbHelper.getFriendCorrespondingYValue(q,"Married"),FRIENDS_RADIUS_LIMIT,mChildFilledPaint);
                                canv.drawText(dbHelper.getNameOfRelation("Friend" + q), dbHelper.getXOfRelation("Friend" + q) - 17, dbHelper.getYOfRelation("Friend"+q), mXHDPIFriendTextPaint);
                                dbHelper.insertXYOfRelation("Friend" + q, dbHelper.getFriendCorrespondingXValue(q,"Married"), dbHelper.getFriendCorrespondingYValue(q,"Married"));
                                friend_x.add(dbHelper.getFriendCorrespondingXValue(q,"Married"));
                                friend_y.add(dbHelper.getFriendCorrespondingYValue(q,"Married"));

                            }
                            for(int w=dbHelper.FetchChildFriendCountFromUserTable("Friend").size()+ 1;w<=34;w++) {

                               // Log.e("Pointer is " + w,"The X value at w is " + dbHelper.getFriendCorrespondingXValue(w,"Married") + " The Y value at w is " + dbHelper.getFriendCorrespondingYValue(w,"Married"));
                                canv.drawCircle(dbHelper.getFriendCorrespondingXValue(w,"Married"),dbHelper.getFriendCorrespondingYValue(w,"Married"), FRIENDS_RADIUS_LIMIT, mCirclePaint);
                            }

                        }
                        else
                        {
                            canv.drawCircle(circle.getCenterX(), circle.getCenterY(), FRIENDS_RADIUS_LIMIT, mCirclePaint);
                        }
                    }
                }
                else
                {

                    //System.out.println("Else of CircleCanvas.member_type!=null");
                    if (circle.radius == FRIENDS_RADIUS_LIMIT) {
                        canv.drawCircle(circle.getCenterX(), circle.getCenterY(), FRIENDS_RADIUS_LIMIT, mCirclePaint);
                    }else if (circle.radius == XHDPI_CHILD_RADIUS_LIMIT) {
                    canv.drawCircle(circle.getCenterX(), circle.getCenterY(), XHDPI_CHILD_RADIUS_LIMIT, mCirclePaint);
                    } else if (circle.radius == XHDPI_PARENTS_RADIUS_LIMIT) {
                        canv.drawCircle(circle.getCenterX(), circle.getCenterY(), XHDPI_PARENTS_RADIUS_LIMIT, mFilledPaint);
                    } else {
                        canv.drawCircle(circle.getCenterX(), circle.getCenterY(), XHDPI_COUPLE_RADIUS_LIMIT, mMarriedPaint);

                    }
                }


            }

        }



    }
San
  • 2,078
  • 1
  • 24
  • 42

1 Answers1

1

I saw your code. So you are using a View to draw all the filled circles. The onDraw method is overloaded with calculations and object instantiation. I suggest that you remove as much as you can from onDraw method. If the calculation can be carried out during the construction of the View, then do it in the constructor and not in the onDraw. You need to keep onDraw as light as possible.

Now is this a good design? Having a View in your case is not a good idea, because a single change will redraw the whole view. Instead I suggest that you create a custom ViewGroup, and have all these filled circles as child to that. That way, when a single circle changes in color or text, you don't need to redraw the whole screen.

Henry
  • 17,490
  • 7
  • 63
  • 98
  • My whole canvas is a single view so using a ViewGroup means that I have multiple views under it and draw only the edited circles again ? I have edited the code in the question so as to give a clear idea, its a bit simple. – San Nov 01 '15 at 10:25
  • Yes. But in your `onDraw`, you are creating so many `bitmap` object. That's very bad. Instead use the underlying bitmap of the view, via the canvas provided in `onDraw`. Don't use `drawBitmap`, but use `drawCircle` or `drawPath`. Long term solution, is to use a `ViewGroup` rather than doing all in a single `View`. – Henry Nov 01 '15 at 10:27
  • But I use drawBitmap to add a image to the circle, and basically all I use is drawCircle and drawPath. Could you be kind enough to provide me with an example to proceed with ViewGroup because I haven't used ViewGroup much ? – San Nov 01 '15 at 10:30
  • Refer this:http://javatechig.com/android/how-to-create-custom-layout-in-android-by-extending-viewgroup-class In the `ViewGroup`, all you will be doing is to arrange your child views in the position you want. That is done in the `onLayout` method. Override that to position all your child views (filled circles) in the place that you want. – Henry Nov 01 '15 at 10:35
  • Thanks Henry, I will take a look at it. – San Nov 01 '15 at 11:20