How to avoid OutOfMemory for TextView containing unlimited ImageSpans?
I am developing a Handwriting note-taking app.
The app works in this way: the user write(draw) a text on the touchscreen, the app convert the handwriting to a Bitmap(getBitmapFromHandwriting()), then use this bitmap to produce a SpannableString and show it to the user in a TextView(In my case, I use an EditText, but to make things simple, let's say it's TextView). Here is the code snippet in the extended TextView: class MyTextView extends TextView{
...
BitmapDrawable bmd = new BitmapDrawable(getBitmapFromHandwriting());
int width = bmd.getIntrinsicWidth();
int height = bmd.getIntrinsicHeight();
bmd.setBounds(
(int)(height/4.0f),
(int)(height/4.0f),
(i开发者_JS百科nt)(width + height/4.0f),
(int)(height*5.0f/4.0f));
final ImageSpan img = new ImageSpan(bmd);
getText().setSpan(img, position, position+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
…
}
In getBitmapFromHandwriting(), the app create a new bitmap for each text drawn by the user.
Everything works fine before the note grows big(means there are lots of bitmaps in the native memory), an OutOfMemoryError is thrown when createBitmap().
After lots of googling, I learned bitmaps use "native memory", which is very limited. I also learned gc for bitmap doesn't happen at the same time with the gc of the JVM take place. So people would better do bitmap.recycle() when the bitmap is surely not necessary any more. From the above knowledge, I think I need to recycle the bitmaps for invisible texts , and load that bitmap only when necessary(i.e., visible) Before recycling a bitmap, I must make sure it won't used in the future, otherwise, will get a "RuntimeException: Canvas: trying to use a recycled bitmap…" i.e., I have to clear the corresponding spans attached to the SpannableString. (By getText().removeSpan(), or getText().clearSpans(), but that's another story.) For doing that, I need to tell which strings are visible and which are invisible. In ViewGroups like GridView, I can call "getFirstVisiblePosition()", but I don't know how to do that for a TextView.I know it's possible to down sample the bitmap to support more bitmaps, but what I want is a TextView supports UNLIMITED ImageSpans.
If it's GridView or ListView, a lazy loading implementation will do the work. But how to do it in a single TextView? Dividing the content to multiple pages should theoretically work for some situations, but in my app, user can also "export" the note. The exporting simply do a copy of the current view(How to do the export without creating new bitmap is another problem, won't discuss in this thread.). If the note is divided to multiple pages, user have to "export" for each page, so it's not an option.My questions are:
1. Is it possible to determine the visible strings in TextView? 2. Is there any better way(patterns) to implement such "TextView containing lots of ImageSpans" without getting OutOfMemoryError?Any idea is appreciated. Thanks in advance!
精彩评论