Fix FontRequest thread leaks and UI bugs related to custom fonts.

This commit is contained in:
Azuo 2021-08-13 22:09:46 +08:00
parent b081b9adbb
commit b3e2d8d843
19 changed files with 103 additions and 59 deletions

View File

@ -63,21 +63,23 @@ object WidgetHelper {
R.array.com_google_android_gms_fonts_certs R.array.com_google_android_gms_fonts_certs
) )
val handlerThread = HandlerThread("generateView")
val callback = object : FontsContractCompat.FontRequestCallback() { val callback = object : FontsContractCompat.FontRequestCallback() {
override fun onTypefaceRetrieved(typeface: Typeface) { override fun onTypefaceRetrieved(typeface: Typeface) {
handlerThread.quit()
function.invoke(typeface) function.invoke(typeface)
} }
override fun onTypefaceRequestFailed(reason: Int) { override fun onTypefaceRequestFailed(reason: Int) {
handlerThread.quit();
function.invoke(null) function.invoke(null)
} }
} }
val handlerThread = HandlerThread("generateView")
handlerThread.start() handlerThread.start()
if (Looper.myLooper() == null) { //if (Looper.myLooper() == null) {
Looper.prepare() // Looper.prepare()
} //}
Handler(handlerThread.looper).run { Handler(handlerThread.looper).run {
FontsContractCompat.requestFont(context, request, callback, this) FontsContractCompat.requestFont(context, request, callback, this)

View File

@ -38,12 +38,15 @@ class CustomFontActivity : AppCompatActivity() {
private lateinit var adapter: SlimAdapter private lateinit var adapter: SlimAdapter
private lateinit var viewModel: CustomFontViewModel private lateinit var viewModel: CustomFontViewModel
private lateinit var binding: ActivityCustomFontBinding private lateinit var binding: ActivityCustomFontBinding
private lateinit var handlerThread: HandlerThread
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(CustomFontViewModel::class.java) viewModel = ViewModelProvider(this).get(CustomFontViewModel::class.java)
binding = ActivityCustomFontBinding.inflate(layoutInflater) binding = ActivityCustomFontBinding.inflate(layoutInflater)
handlerThread = HandlerThread("listCustomFonts")
handlerThread.start()
binding.listView.setHasFixedSize(true) binding.listView.setHasFixedSize(true)
val mLayoutManager = LinearLayoutManager(this) val mLayoutManager = LinearLayoutManager(this)
@ -64,14 +67,17 @@ class CustomFontActivity : AppCompatActivity() {
injector injector
.text(R.id.text, item) .text(R.id.text, item)
.with<TextView>(R.id.text) { .with<TextView>(R.id.text) {
val googleSans: Typeface = when (Preferences.customFontVariant) { val googleSans: Typeface? = androidx.core.content.res.ResourcesCompat.getFont(
"100" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_thin.ttf") this,
"200" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_light.ttf") when (Preferences.customFontVariant) {
"500" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_medium.ttf") "100" -> R.font.google_sans_thin
"700" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_bold.ttf") "200" -> R.font.google_sans_light
"800" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_black.ttf") "500" -> R.font.google_sans_medium
else -> Typeface.createFromAsset(this.assets, "fonts/google_sans_regular.ttf") "700" -> R.font.google_sans_bold
} "800" -> R.font.google_sans_black
else -> R.font.google_sans_regular
}
)
it.typeface = googleSans it.typeface = googleSans
} }
@ -97,32 +103,49 @@ class CustomFontActivity : AppCompatActivity() {
) )
val callback = object : FontsContractCompat.FontRequestCallback() { class Callback : FontsContractCompat.FontRequestCallback() {
override fun onTypefaceRetrieved(typeface: Typeface) { var handler: Handler? = Handler(handlerThread.looper)
it.typeface = typeface
it.isVisible = true
it.measure( fun cancel() {
ViewGroup.LayoutParams.MATCH_PARENT, if (handler != null) {
ViewGroup.LayoutParams.WRAP_CONTENT handler!!.removeCallbacksAndMessages(null)
) handler = null
}
}
protected fun finalize() {
cancel()
}
override fun onTypefaceRetrieved(typeface: Typeface) {
if (it.tag == this) {
it.tag = null
it.typeface = typeface
it.setTextColor(getColor(R.color.colorPrimaryText))
}
} }
override fun onTypefaceRequestFailed(reason: Int) { override fun onTypefaceRequestFailed(reason: Int) {
it.isVisible = false if (it.tag == this) {
it.layoutParams = it.layoutParams.apply { it.tag = null
height = 0 //it.text = item.fontFamily + " ($reason)"
it.setTextColor(getColor(R.color.errorColorText))
} }
} }
} }
val handlerThread = HandlerThread(item.fontFamily) (it.tag as Callback?)?.cancel()
handlerThread.start() val callback = Callback()
val mHandler = Handler(handlerThread.looper) it.tag = callback
it.typeface = null
it.setTextColor(getColor(R.color.colorSecondaryText))
val mHandler = callback.handler!!
FontsContractCompat.requestFont(this, request, callback, mHandler) FontsContractCompat.requestFont(this, request, callback, mHandler)
} }
injector.clicked(R.id.text) { injector.clicked(R.id.text) {
if ((it as TextView).typeface == null) return@clicked
val dialog = BottomSheetMenu<Int>(this, header = item.fontFamily) val dialog = BottomSheetMenu<Int>(this, header = item.fontFamily)
if (item.fontVariants.isEmpty()) { if (item.fontVariants.isEmpty()) {
dialog.addItem(SettingsStringHelper.getVariantLabel(this, "regular"), -1) dialog.addItem(SettingsStringHelper.getVariantLabel(this, "regular"), -1)
@ -147,6 +170,12 @@ class CustomFontActivity : AppCompatActivity() {
setContentView(binding.root) setContentView(binding.root)
} }
override fun onDestroy() {
handlerThread.quit()
filterJob?.cancel()
super.onDestroy()
}
private var filterJob: Job? = null private var filterJob: Job? = null
private fun subscribeUi(binding: ActivityCustomFontBinding, viewModel: CustomFontViewModel) { private fun subscribeUi(binding: ActivityCustomFontBinding, viewModel: CustomFontViewModel) {
@ -204,6 +233,13 @@ class CustomFontActivity : AppCompatActivity() {
adapter.updateData(filteredList) adapter.updateData(filteredList)
binding.loader.visibility = View.INVISIBLE binding.loader.visibility = View.INVISIBLE
} }
} else {
delay(200)
withContext(Dispatchers.Main) {
adapter.updateData(listOf(getString(R.string.custom_font_subtitle_1)).filter {
it.contains(search ?: "", ignoreCase = true)
})
}
} }
} }
} }

View File

@ -276,7 +276,7 @@ class TypographyFragment : Fragment() {
Intent(requireContext(), CustomFontActivity::class.java), Intent(requireContext(), CustomFontActivity::class.java),
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code
) )
} else if (value != Constants.CUSTOM_FONT_DOWNLOADED) { } else if (value != Preferences.customFont) {
Preferences.bulk { Preferences.bulk {
customFont = value customFont = value
customFontFile = "" customFontFile = ""

View File

@ -876,14 +876,17 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) {
// Custom Font // Custom Font
if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) { if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) {
val googleSans: Typeface = when (Preferences.customFontVariant) { val googleSans: Typeface? = androidx.core.content.res.ResourcesCompat.getFont(
"100" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_thin.ttf") context,
"200" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_light.ttf") when (Preferences.customFontVariant) {
"500" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_medium.ttf") "100" -> R.font.google_sans_thin
"700" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_bold.ttf") "200" -> R.font.google_sans_light
"800" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_black.ttf") "500" -> R.font.google_sans_medium
else -> Typeface.createFromAsset(context.assets, "fonts/google_sans_regular.ttf") "700" -> R.font.google_sans_bold
} "800" -> R.font.google_sans_black
else -> R.font.google_sans_regular
}
)
listOf<TextView>( listOf<TextView>(
bindingView.date, bindingView.date,

View File

@ -919,14 +919,17 @@ class StandardWidget(val context: Context) {
// Custom Font // Custom Font
if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) { if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) {
val googleSans: Typeface = when (Preferences.customFontVariant) { val googleSans: Typeface? = androidx.core.content.res.ResourcesCompat.getFont(
"100" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_thin.ttf") context,
"200" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_light.ttf") when (Preferences.customFontVariant) {
"500" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_medium.ttf") "100" -> R.font.google_sans_thin
"700" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_bold.ttf") "200" -> R.font.google_sans_light
"800" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_black.ttf") "500" -> R.font.google_sans_medium
else -> Typeface.createFromAsset(context.assets, "fonts/google_sans_regular.ttf") "700" -> R.font.google_sans_bold
} "800" -> R.font.google_sans_black
else -> R.font.google_sans_regular
}
)
listOf<TextView>( listOf<TextView>(
bindingView.date, bindingView.date,

View File

@ -9,6 +9,14 @@
app:fontStyle="italic" app:fontStyle="italic"
app:fontWeight="400" app:fontWeight="400"
app:font="@font/google_sans_italic" /> app:font="@font/google_sans_italic" />
<font
app:fontStyle="normal"
app:fontWeight="100"
app:font="@font/google_sans_thin" />
<font
app:fontStyle="italic"
app:fontWeight="100"
app:font="@font/google_sans_thin_italic" />
<font <font
app:fontStyle="normal" app:fontStyle="normal"
app:fontWeight="200" app:fontWeight="200"
@ -19,34 +27,26 @@
app:font="@font/google_sans_light_italic" /> app:font="@font/google_sans_light_italic" />
<font <font
app:fontStyle="normal" app:fontStyle="normal"
app:fontWeight="300" app:fontWeight="500"
app:font="@font/google_sans_thin" />
<font
app:fontStyle="italic"
app:fontWeight="300"
app:font="@font/google_sans_thin_italic" />
<font
app:fontStyle="normal"
app:fontWeight="700"
app:font="@font/google_sans_medium" /> app:font="@font/google_sans_medium" />
<font <font
app:fontStyle="italic" app:fontStyle="italic"
app:fontWeight="700" app:fontWeight="500"
app:font="@font/google_sans_medium_italic" /> app:font="@font/google_sans_medium_italic" />
<font <font
app:fontStyle="normal" app:fontStyle="normal"
app:fontWeight="800" app:fontWeight="700"
app:font="@font/google_sans_bold" /> app:font="@font/google_sans_bold" />
<font <font
app:fontStyle="italic" app:fontStyle="italic"
app:fontWeight="800" app:fontWeight="700"
app:font="@font/google_sans_bold_italic" /> app:font="@font/google_sans_bold_italic" />
<font <font
app:fontStyle="normal" app:fontStyle="normal"
app:fontWeight="900" app:fontWeight="800"
app:font="@font/google_sans_black" /> app:font="@font/google_sans_black" />
<font <font
app:fontStyle="italic" app:fontStyle="italic"
app:fontWeight="900" app:fontWeight="800"
app:font="@font/google_sans_black_italic" /> app:font="@font/google_sans_black_italic" />
</font-family> </font-family>

View File

@ -139,10 +139,10 @@
<item name="android:gravity">center_horizontal</item> <item name="android:gravity">center_horizontal</item>
</style> </style>
<style name="AnotherWidget.Widget.Date" parent="AnotherWidget.Subtitle"> <style name="AnotherWidget.Widget.Date" parent="AnotherWidget.Widget.Subtitle">
</style> </style>
<style name="AnotherWidget.Widget.Date.Big" parent="AnotherWidget.Title"> <style name="AnotherWidget.Widget.Date.Big" parent="AnotherWidget.Widget.Title">
<item name="android:textSize">22sp</item> <item name="android:textSize">22sp</item>
</style> </style>