Memory leaks with custom font for set custom font
You should cache the TypeFace, otherwise you might risk memory leaks on older handsets. Caching will increase speed as well since it's not super fast to read from assets all the time.
public class FontCache {
private static Hashtable<String, Typeface> fontCache = new Hashtable<String, Typeface>();
public static Typeface get(String name, Context context) {
Typeface tf = fontCache.get(name);
if(tf == null) {
try {
tf = Typeface.createFromAsset(context.getAssets(), name);
}
catch (Exception e) {
return null;
}
fontCache.put(name, tf);
}
return tf;
}
}
I gave a full example on how to load custom fonts and style textviews as an answer to a similar question. You seem to be doing most of it right, but you should cache the font as recommended above.
Using Custom Fonts Properly in Android
You should find your answer here.
Basically you need to build your own system to cache those typefaces after you create them (and therefore you'll only be creating each typeface once).
RuntimeException: native typeface cannot be made or memory leak for custom TextView loading font
Okay, so I finally figured that instantiating a TypeFace
object inside a TextView
class would cause so much load each time that same TextView
is instantiated. This caused my app to lag and resulted to OutOfMemoryException
eventually. So what I did was to create a different custom TypeFace
class that would call my fonts from the assets so that it instantiates from the TypeFace
class and not from the TextView
class.
Here's my TypeFaces class:
public class TypeFaces {
private static final Hashtable<String, Typeface> cache = new Hashtable<String, Typeface>();
public static Typeface getTypeFace(Context context, String assetPath) {
synchronized (cache) {
if (!cache.containsKey(assetPath)) {
try {
Typeface typeFace = Typeface.createFromAsset(
context.getAssets(), assetPath);
cache.put(assetPath, typeFace);
} catch (Exception e) {
Log.e("TypeFaces", "Typeface not loaded.");
return null;
}
}
return cache.get(assetPath);
}
}
}
And the custom TextView class:
public class TextViewHirakaku extends TextView {
public TextViewHirakaku(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public TextViewHirakaku(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TextViewHirakaku(Context context) {
super(context);
}
public void setTypeface(Typeface tf, int style) {
if (style == Typeface.BOLD) {
super.setTypeface(TypeFaces.getTypeFace(getContext(),
"fonts/hirakakupronbold.ttf"));
} else if (style == Typeface.ITALIC) {
super.setTypeface(TypeFaces.getTypeFace(getContext(),
"fonts/hirakakupronitalic.ttf"));
} else {
super.setTypeface(TypeFaces.getTypeFace(getContext(),
"fonts/hirakakupron.ttf"));
}
}
}
Notice that I'm now calling getTypeFace
method from TypeFaces
class here.
Memory leak when using custom text in React Native
You can try loading the fonts in async manner and keep a check in your useEffect
to setState only if its not unmounted, like given in this expo documentation using-fontloadasync-instead-of-the-usefonts-hook
Here is the expo snack example
Also, I would suggest to load fonts from local cache instead from direct web, which will increase the app size a little bit, but fonts will load much faster, just like given in the above example.
Memory leak when using custom text field in SwiftUI
Here is fixed part - to avoid cycling it needs to update only with really new value
Tested with Xcode 12 / iOS 14
.onReceive(Just(textValue)) {
guard self.hasInitialTextValue else {
// We don't have a usable `textValue` yet -- bail out.
return
}
// This is the only place we update `value`.
let newValue = self.formatter.number(from: $0)?.decimalValue
if newValue != self.value {
self.value = newValue
}
}
To use or not to use Custom Fonts on Android
Besides what CommonsWare said, (that was my first accepted answer), I have found a major bug, that creates memory leaks when using Custom Fonts:
http://code.google.com/p/android/issues/detail?id=9904#c7
Because of this, I tend to think that it is not a good ideia to use them.. or at least beware when you use them!
If you do need to use them, you can use this to avoid the biggest part of the memory leaks:
public class Typefaces {
private static final String TAG = "Typefaces";
private static final Hashtable<String, Typeface> cache = new Hashtable<String, Typeface>();
public static Typeface get(Context c, String assetPath) {
synchronized (cache) {
if (!cache.containsKey(assetPath)) {
try {
Typeface t = Typeface.createFromAsset(c.getAssets(),
assetPath);
cache.put(assetPath, t);
} catch (Exception e) {
Log.e(TAG, "Could not get typeface '" + assetPath
+ "' because " + e.getMessage());
return null;
}
}
return cache.get(assetPath);
}
}
}
Related Topics
Understanding Recyclerview Sethasfixedsize
How to Take Camera Capture Without a Preview from a Service or Thread
How to Change the Size of a Switch Widget
How to Run an Android App in Background
Retrofit - Multipart Request: Required Multipartfile Parameter 'File' Is Not Present
Multiple Screen Support in Android
Android: When Should I Use a Handler() and When Should I Use a Thread
Add Floating Point Value to Android Resources/Values
Gatt Callback Fails to Register
Recyclerview Changing Items During Scroll
Android Recyclerview:Notifydatasetchanged() Illegalstateexception
Android: How to Change Checkbox Size
How to Get Name of Wifi-Network Out of Android Using Android API
Differencebetween Activity and Context
Android Actionbar How to Add Supporting Library V7 Appcompat for Eclipse
Android Studio Compile Error "Content Is Not Allowed in Prolog"