diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt b/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt index 38d72fc3a..6be4224a8 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt @@ -41,6 +41,7 @@ import com.keylesspalace.tusky.util.emojify import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.loadAvatar import com.keylesspalace.tusky.util.show +import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.viewmodel.AccountsInListViewModel import com.keylesspalace.tusky.viewmodel.State @@ -63,10 +64,10 @@ class AccountsInListFragment : DialogFragment(), Injectable { private val adapter = Adapter() private val searchAdapter = SearchAdapter() - private val radius by lazy { resources.getDimensionPixelSize(R.dimen.avatar_radius_48dp) } - private val pm by lazy { PreferenceManager.getDefaultSharedPreferences(requireContext()) } - private val animateAvatar by lazy { pm.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false) } - private val animateEmojis by lazy { pm.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) } + private val radius by unsafeLazy { resources.getDimensionPixelSize(R.dimen.avatar_radius_48dp) } + private val pm by unsafeLazy { PreferenceManager.getDefaultSharedPreferences(requireContext()) } + private val animateAvatar by unsafeLazy { pm.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false) } + private val animateEmojis by unsafeLazy { pm.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt b/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt index 85518b239..1e1473256 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt @@ -96,6 +96,7 @@ import com.keylesspalace.tusky.util.getDimension import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.reduceSwipeSensitivity import com.keylesspalace.tusky.util.show +import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.updateShortcut import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.visible @@ -162,7 +163,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje private var unreadAnnouncementsCount = 0 - private val preferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) } + private val preferences by unsafeLazy { PreferenceManager.getDefaultSharedPreferences(this) } private lateinit var glide: RequestManager diff --git a/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt b/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt index d476ea728..cb492424a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/TabPreferenceActivity.kt @@ -46,6 +46,7 @@ import com.keylesspalace.tusky.databinding.ActivityTabPreferenceBinding import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.util.onTextChanged +import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.visible import io.reactivex.rxjava3.core.Single @@ -70,9 +71,9 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene private var tabsChanged = false - private val selectedItemElevation by lazy { resources.getDimension(R.dimen.selected_drag_item_elevation) } + private val selectedItemElevation by unsafeLazy { resources.getDimension(R.dimen.selected_drag_item_elevation) } - private val hashtagRegex by lazy { Pattern.compile("([\\w_]*[\\p{Alpha}_][\\w_]*)", Pattern.CASE_INSENSITIVE) } + private val hashtagRegex by unsafeLazy { Pattern.compile("([\\w_]*[\\p{Alpha}_][\\w_]*)", Pattern.CASE_INSENSITIVE) } private val onFabDismissedCallback = object : OnBackPressedCallback(false) { override fun handleOnBackPressed() { diff --git a/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt index 4f1627ae7..7f17bfe58 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt @@ -82,6 +82,7 @@ import com.keylesspalace.tusky.util.parseAsMastodonHtml import com.keylesspalace.tusky.util.reduceSwipeSensitivity import com.keylesspalace.tusky.util.setClickableText import com.keylesspalace.tusky.util.show +import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.view.showMuteAccountDialog @@ -109,7 +110,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI private lateinit var accountFieldAdapter: AccountFieldAdapter - private val preferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) } + private val preferences by unsafeLazy { PreferenceManager.getDefaultSharedPreferences(this) } private var followState: FollowState = FollowState.NOT_FOLLOWING private var blocking: Boolean = false diff --git a/app/src/main/java/com/keylesspalace/tusky/components/announcements/AnnouncementsActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/announcements/AnnouncementsActivity.kt index b353fe866..14fbcf8cc 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/announcements/AnnouncementsActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/announcements/AnnouncementsActivity.kt @@ -39,6 +39,7 @@ import com.keylesspalace.tusky.util.Loading import com.keylesspalace.tusky.util.Success import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.show +import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.view.EmojiPicker import javax.inject.Inject @@ -54,8 +55,8 @@ class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener, private lateinit var adapter: AnnouncementAdapter - private val picker by lazy { EmojiPicker(this) } - private val pickerDialog by lazy { + private val picker by unsafeLazy { EmojiPicker(this) } + private val pickerDialog by unsafeLazy { PopupWindow(this) .apply { contentView = picker diff --git a/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt index da074c698..b49b5e7f1 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt @@ -100,6 +100,7 @@ import com.keylesspalace.tusky.util.modernLanguageCode import com.keylesspalace.tusky.util.onTextChanged import com.keylesspalace.tusky.util.setDrawableTint import com.keylesspalace.tusky.util.show +import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.visible import com.mikepenz.iconics.IconicsDrawable @@ -139,7 +140,7 @@ class ComposeActivity : private var photoUploadUri: Uri? = null - private val preferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) } + private val preferences by unsafeLazy { PreferenceManager.getDefaultSharedPreferences(this) } @VisibleForTesting var maximumTootCharacters = InstanceInfoRepository.DEFAULT_CHARACTER_LIMIT diff --git a/app/src/main/java/com/keylesspalace/tusky/components/preference/AccountPreferencesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/preference/AccountPreferencesFragment.kt index a883f73c5..25024d00a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/preference/AccountPreferencesFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/preference/AccountPreferencesFragment.kt @@ -53,6 +53,7 @@ import com.keylesspalace.tusky.util.getInitialLanguage import com.keylesspalace.tusky.util.getLocaleList import com.keylesspalace.tusky.util.getTuskyDisplayName import com.keylesspalace.tusky.util.makeIcon +import com.keylesspalace.tusky.util.unsafeLazy import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.utils.colorInt @@ -72,7 +73,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable { @Inject lateinit var eventHub: EventHub - private val iconSize by lazy { resources.getDimensionPixelSize(R.dimen.preference_icon_size) } + private val iconSize by unsafeLazy { resources.getDimensionPixelSize(R.dimen.preference_icon_size) } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { val context = requireContext() diff --git a/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt index 5d6c1ea27..615c9cd5b 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt @@ -34,6 +34,7 @@ import com.keylesspalace.tusky.util.LocaleManager import com.keylesspalace.tusky.util.deserialize import com.keylesspalace.tusky.util.makeIcon import com.keylesspalace.tusky.util.serialize +import com.keylesspalace.tusky.util.unsafeLazy import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import de.c1710.filemojicompat_ui.views.picker.preference.EmojiPickerPreference @@ -47,7 +48,7 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable { @Inject lateinit var localeManager: LocaleManager - private val iconSize by lazy { resources.getDimensionPixelSize(R.dimen.preference_icon_size) } + private val iconSize by unsafeLazy { resources.getDimensionPixelSize(R.dimen.preference_icon_size) } enum class ReadingOrder { /** User scrolls up, reading statuses oldest to newest */ diff --git a/app/src/main/java/com/keylesspalace/tusky/components/search/SearchActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/search/SearchActivity.kt index 209548e88..beb31611b 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/search/SearchActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/search/SearchActivity.kt @@ -31,6 +31,7 @@ import com.keylesspalace.tusky.databinding.ActivitySearchBinding import com.keylesspalace.tusky.di.ViewModelFactory import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.util.reduceSwipeSensitivity +import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.viewBinding import dagger.android.DispatchingAndroidInjector import dagger.android.HasAndroidInjector @@ -47,7 +48,7 @@ class SearchActivity : BottomSheetActivity(), HasAndroidInjector { private val binding by viewBinding(ActivitySearchBinding::inflate) - private val preferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) } + private val preferences by unsafeLazy { PreferenceManager.getDefaultSharedPreferences(this) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt index 6d0ff7ae7..fe7b5d145 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt @@ -61,6 +61,7 @@ import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate import com.keylesspalace.tusky.util.StatusDisplayOptions import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.show +import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.viewdata.AttachmentViewData import com.keylesspalace.tusky.viewdata.StatusViewData @@ -86,7 +87,7 @@ class TimelineFragment : @Inject lateinit var eventHub: EventHub - private val viewModel: TimelineViewModel by lazy { + private val viewModel: TimelineViewModel by unsafeLazy { if (kind == TimelineViewModel.Kind.HOME) { ViewModelProvider(this, viewModelFactory)[CachedTimelineViewModel::class.java] } else { diff --git a/app/src/main/java/com/keylesspalace/tusky/service/SendStatusService.kt b/app/src/main/java/com/keylesspalace/tusky/service/SendStatusService.kt index 90babc031..39dcefa02 100644 --- a/app/src/main/java/com/keylesspalace/tusky/service/SendStatusService.kt +++ b/app/src/main/java/com/keylesspalace/tusky/service/SendStatusService.kt @@ -34,6 +34,7 @@ import com.keylesspalace.tusky.entity.NewPoll import com.keylesspalace.tusky.entity.NewStatus import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.network.MastodonApi +import com.keylesspalace.tusky.util.unsafeLazy import dagger.android.AndroidInjection import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -66,7 +67,7 @@ class SendStatusService : Service(), Injectable { private val statusesToSend = ConcurrentHashMap() private val sendJobs = ConcurrentHashMap() - private val notificationManager by lazy { getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager } + private val notificationManager by unsafeLazy { getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager } override fun onCreate() { AndroidInjection.inject(this) diff --git a/app/src/main/java/com/keylesspalace/tusky/util/Lazy.kt b/app/src/main/java/com/keylesspalace/tusky/util/Lazy.kt new file mode 100644 index 000000000..874455666 --- /dev/null +++ b/app/src/main/java/com/keylesspalace/tusky/util/Lazy.kt @@ -0,0 +1,5 @@ +package com.keylesspalace.tusky.util + +@Suppress("NOTHING_TO_INLINE") +inline fun unsafeLazy(noinline initializer: () -> T): Lazy = + lazy(LazyThreadSafetyMode.NONE, initializer)