Skip to content

Commit 4367741

Browse files
oprisnikmeta-codesync[bot]
authored andcommitted
Decouple Showcase initialization
Differential Revision: D97101508 fbshipit-source-id: 24c77b8e970a29e278317dde2e936a1a77b74708
1 parent 4117d32 commit 4367741

59 files changed

Lines changed: 436 additions & 250 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎samples/showcase/src/main/AndroidManifest.xml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@
3434
</intent-filter>
3535
</activity>
3636

37+
<activity
38+
android:name=".ShowcaseListActivity"
39+
android:label="Fresco Showcase"
40+
android:theme="@style/AppTheme"
41+
android:exported="true" />
42+
3743
<activity
3844
android:name=".vito.transition.ImageDetailsActivity"
3945
android:label="@string/vito_transition_details_title"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.facebook.fresco.samples.showcase">
4+
<application>
5+
<activity android:name=".ShowcaseListActivity" android:label="Fresco Showcase"
6+
android:theme="@style/AppTheme" android:exported="false" />
7+
<activity android:name=".vito.transition.ImageDetailsActivity"
8+
android:label="@string/vito_transition_details_title"
9+
android:theme="@style/AppTheme.ImageDetails" android:exported="false" />
10+
</application>
11+
</manifest>

‎samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/BaseShowcaseFragment.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
public abstract class BaseShowcaseFragment extends Fragment {
1717

1818
public ImageUriProvider sampleUris() {
19-
return ShowcaseApplication.Companion.getImageUriProvider();
19+
return ShowcaseProvider.INSTANCE.getImageUriProvider();
2020
}
2121
}

‎samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/ExampleDatabase.kt‎

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,9 @@
77

88
package com.facebook.fresco.samples.showcase
99

10-
import com.facebook.fresco.samples.showcase.drawee.*
11-
import com.facebook.fresco.samples.showcase.imageformat.color.ImageFormatColorFragment
1210
import com.facebook.fresco.samples.showcase.imageformat.datauri.ImageFormatDataUriFragment
1311
import com.facebook.fresco.samples.showcase.imageformat.gif.ImageFormatGifFragment
14-
import com.facebook.fresco.samples.showcase.imageformat.keyframes.ImageFormatKeyframesFragment
15-
import com.facebook.fresco.samples.showcase.imageformat.override.ImageFormatOverrideExample
1612
import com.facebook.fresco.samples.showcase.imageformat.pjpeg.ImageFormatProgressiveJpegFragment
17-
import com.facebook.fresco.samples.showcase.imageformat.svg.ImageFormatSvgFragment
1813
import com.facebook.fresco.samples.showcase.imageformat.webp.ImageFormatWebpFragment
1914
import com.facebook.fresco.samples.showcase.imageformat.xml.ImageFormatXmlFragment
2015
import com.facebook.fresco.samples.showcase.imagepipeline.*
@@ -55,12 +50,8 @@ object ExampleDatabase {
5550
"Image Formats",
5651
listOf(
5752
ExampleItem("Progressive JPEG") { ImageFormatProgressiveJpegFragment() },
58-
ExampleItem("Color") { ImageFormatColorFragment() },
5953
ExampleItem("GIF") { ImageFormatGifFragment() },
6054
ExampleItem("WebP") { ImageFormatWebpFragment() },
61-
ExampleItem("SVG") { ImageFormatSvgFragment() },
62-
ExampleItem("Keyframes") { ImageFormatKeyframesFragment() },
63-
ExampleItem("Decoder Override") { ImageFormatOverrideExample() },
6455
ExampleItem("Data URI") { ImageFormatDataUriFragment() },
6556
ExampleItem("XML") { ImageFormatXmlFragment() },
6657
),
@@ -79,17 +70,13 @@ object ExampleDatabase {
7970
ExampleItem("Vito Litho: Image Options configurator") {
8071
FrescoVitoLithoImageOptionsConfigFragment()
8172
},
82-
ExampleItem("Vito Litho: Sections (RecyclerView)") {
83-
FrescoVitoLithoSectionsFragment()
84-
},
8573
ExampleItem(
8674
"Vito Litho: Listener",
8775
FrescoVitoLithoListenerExample,
8876
"Vito Litho component with listener.",
8977
),
9078
ExampleItem("Scale Type") { VitoScaleTypeFragment() },
9179
ExampleItem("Rotation") { VitoRotationFragment() },
92-
ExampleItem("Vito Litho: Gallery") { FrescoVitoLithoGalleryFragment() },
9380
ExampleItem("Vito View: Simple") { VitoViewSimpleFragment() },
9481
ExampleItem("Vito View: Simple 2") { VitoSimpleFragment() },
9582
ExampleItem("Vito View: Recycler") { VitoViewRecyclerFragment() },
@@ -110,7 +97,6 @@ object ExampleDatabase {
11097
"Vito Litho DrawableImageSource",
11198
FrescoVitoLithoDrawableImageSourceExample,
11299
),
113-
ExampleItem("Media Provider") { VitoMediaPickerFragment() },
114100
ExampleItem("Multi URI") { MultiUriFragment() },
115101
ExampleItem("Placeholder, Progress, Failure") { ImageLayersFragment() },
116102
ExampleItem("Rounded Corners") { VitoRoundedCornersFragment() },

‎samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/MainActivity.kt‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class MainActivity : AppCompatActivity() {
3333

3434
override fun onCreate(savedInstanceState: Bundle?) {
3535
super.onCreate(savedInstanceState)
36+
ShowcaseProvider.initIfNeeded(this)
3637
setContentView(R.layout.activity_main)
3738
setSupportActionBar(toolbar)
3839

@@ -118,8 +119,8 @@ class MainActivity : AppCompatActivity() {
118119

119120
override fun onOptionsItemSelected(item: MenuItem): Boolean {
120121
when (item.itemId) {
121-
R.id.action_next_image -> ShowcaseApplication.imageSelector.selectNext(this)
122-
R.id.action_prev_image -> ShowcaseApplication.imageSelector.selectPrevious(this)
122+
R.id.action_next_image -> ShowcaseProvider.imageSelector.selectNext(this)
123+
R.id.action_prev_image -> ShowcaseProvider.imageSelector.selectPrevious(this)
123124
R.id.action_settings -> showFragment(ExampleDatabase.settings)
124125
R.id.action_edit_image -> showImageOptionsEditor()
125126
}
@@ -128,7 +129,7 @@ class MainActivity : AppCompatActivity() {
128129

129130
private fun showImageOptionsEditor() {
130131
supportFragmentManager.let {
131-
ImageOptionsBottomSheet.newInstance(ShowcaseApplication.imageSelector, Bundle()).apply {
132+
ImageOptionsBottomSheet.newInstance(ShowcaseProvider.imageSelector, Bundle()).apply {
132133
show(it, tag)
133134
}
134135
}
@@ -157,11 +158,11 @@ class MainActivity : AppCompatActivity() {
157158
fragmentTransaction.commit()
158159

159160
setTitle(title)
160-
ShowcaseApplication.imageTracker.reset()
161+
ShowcaseProvider.imageTracker.reset()
161162
}
162163

163164
private fun maybeShowUriOverrideReminder() {
164-
if (ShowcaseApplication.imageUriProvider.uriOverride == null) {
165+
if (ShowcaseProvider.imageUriProvider.uriOverride == null) {
165166
return
166167
}
167168
Snackbar.make(contentMain, R.string.snackbar_uri_override_reminder_text, Snackbar.LENGTH_LONG)

‎samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/ShowcaseApplication.kt‎

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import com.facebook.fresco.vito.core.DefaultFrescoVitoConfig
3535
import com.facebook.fresco.vito.core.FrescoVitoConfig
3636
import com.facebook.fresco.vito.core.impl.DebugOverlayHandler
3737
import com.facebook.fresco.vito.init.FrescoVito
38-
import com.facebook.fresco.vito.provider.FrescoVitoProvider
3938
import com.facebook.fresco.vito.provider.impl.NoOpCallerContextVerifier
4039
import com.facebook.fresco.vito.provider.impl.kotlin.KFrescoVitoProvider
4140
import com.facebook.fresco.vito.tools.liveeditor.ImageSelector
@@ -62,7 +61,7 @@ class ShowcaseApplication : Application() {
6261

6362
override fun onCreate() {
6463
super.onCreate()
65-
imageUriProvider = ImageUriProvider(applicationContext)
64+
ShowcaseProvider.initIfNeeded(applicationContext)
6665
FLog.minimumLoggingLevel = FLog.VERBOSE
6766
val forwardingRequestListener = ForwardingRequestListener()
6867
val requestListeners =
@@ -126,14 +125,7 @@ class ShowcaseApplication : Application() {
126125
}
127126

128127
Fresco.initialize(this, imagePipelineConfig, draweeConfigBuilder.build())
129-
imageTracker = ImageTracker()
130128
initVito(resources)
131-
imageSelector =
132-
ImageSelector(
133-
imageTracker,
134-
FrescoVitoProvider.getImagePipeline(),
135-
FrescoVitoProvider.getController(),
136-
)
137129
val context = this
138130
Stetho.initialize(
139131
Stetho.newInitializerBuilder(context)
@@ -203,13 +195,13 @@ class ShowcaseApplication : Application() {
203195

204196
companion object {
205197
private val sFlipperImageTracker = FlipperImageTracker()
206-
lateinit var imageTracker: ImageTracker
207-
private set
198+
val imageTracker: ImageTracker
199+
get() = ShowcaseProvider.imageTracker
208200

209-
lateinit var imageUriProvider: ImageUriProvider
210-
private set
201+
val imageUriProvider: ImageUriProvider
202+
get() = ShowcaseProvider.imageUriProvider
211203

212-
lateinit var imageSelector: ImageSelector
213-
private set
204+
val imageSelector: ImageSelector
205+
get() = ShowcaseProvider.imageSelector
214206
}
215207
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.fresco.samples.showcase
9+
10+
import android.annotation.SuppressLint
11+
import android.os.Bundle
12+
import android.view.LayoutInflater
13+
import android.view.View
14+
import android.view.ViewGroup
15+
import android.widget.FrameLayout
16+
import android.widget.TextView
17+
import androidx.activity.OnBackPressedCallback
18+
import androidx.appcompat.app.AppCompatActivity
19+
import androidx.recyclerview.widget.LinearLayoutManager
20+
import androidx.recyclerview.widget.RecyclerView
21+
22+
/**
23+
* A simple list-based activity showing all Fresco Showcase sample screens. Can be launched from
24+
* FB4A internal settings or any other host app where Fresco is already initialized.
25+
*/
26+
@SuppressLint(
27+
"BadSuperClassFragmentActivity",
28+
"EndpointWithoutSwitchOff",
29+
"UseOfBasicFragmentClass",
30+
)
31+
class ShowcaseListActivity : AppCompatActivity() {
32+
33+
companion object {
34+
private const val FRAGMENT_CONTAINER_ID = 0x00ffffff
35+
}
36+
37+
private lateinit var recyclerView: RecyclerView
38+
39+
private val backCallback =
40+
object : OnBackPressedCallback(false) {
41+
override fun handleOnBackPressed() {
42+
val fm = supportFragmentManager
43+
val fragment = fm.findFragmentById(FRAGMENT_CONTAINER_ID)
44+
if (fragment != null) {
45+
fm.beginTransaction().remove(fragment).commit()
46+
recyclerView.visibility = View.VISIBLE
47+
title = "Fresco Showcase"
48+
isEnabled = false
49+
}
50+
}
51+
}
52+
53+
override fun onCreate(savedInstanceState: Bundle?) {
54+
super.onCreate(savedInstanceState)
55+
ShowcaseProvider.initIfNeeded(this)
56+
57+
val root = FrameLayout(this)
58+
root.fitsSystemWindows = true
59+
60+
recyclerView = RecyclerView(this)
61+
recyclerView.id = android.R.id.list
62+
recyclerView.layoutManager = LinearLayoutManager(this)
63+
root.addView(recyclerView)
64+
65+
val fragmentContainer = FrameLayout(this)
66+
fragmentContainer.id = FRAGMENT_CONTAINER_ID
67+
root.addView(fragmentContainer)
68+
69+
setContentView(root)
70+
71+
title = "Fresco Showcase"
72+
73+
onBackPressedDispatcher.addCallback(this, backCallback)
74+
75+
val items = buildListItems()
76+
recyclerView.adapter = ShowcaseListAdapter(items) { exampleItem -> showFragment(exampleItem) }
77+
}
78+
79+
private fun buildListItems(): List<ListItem> {
80+
val items = mutableListOf<ListItem>()
81+
for (category in ExampleDatabase.examples) {
82+
items.add(ListItem.Header(category.name))
83+
for (example in category.examples) {
84+
items.add(ListItem.Sample(example))
85+
}
86+
}
87+
return items
88+
}
89+
90+
private fun showFragment(item: ExampleItem) {
91+
recyclerView.visibility = View.GONE
92+
supportFragmentManager
93+
.beginTransaction()
94+
.replace(FRAGMENT_CONTAINER_ID, item.createFragment())
95+
.commit()
96+
title = item.title
97+
backCallback.isEnabled = true
98+
}
99+
}
100+
101+
sealed class ListItem {
102+
data class Header(val name: String) : ListItem()
103+
104+
data class Sample(val item: ExampleItem) : ListItem()
105+
}
106+
107+
private class ShowcaseListAdapter(
108+
private val items: List<ListItem>,
109+
private val onItemClick: (ExampleItem) -> Unit,
110+
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
111+
112+
override fun getItemViewType(position: Int): Int =
113+
when (items[position]) {
114+
is ListItem.Header -> VIEW_TYPE_HEADER
115+
is ListItem.Sample -> VIEW_TYPE_SAMPLE
116+
}
117+
118+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
119+
val inflater = LayoutInflater.from(parent.context)
120+
return when (viewType) {
121+
VIEW_TYPE_HEADER -> {
122+
val view =
123+
inflater.inflate(android.R.layout.simple_list_item_1, parent, false).apply {
124+
val textView = findViewById<TextView>(android.R.id.text1)
125+
textView.textSize = 14f
126+
textView.setTextColor(0xFF757575.toInt())
127+
val padding = (12 * resources.displayMetrics.density).toInt()
128+
textView.setPadding(padding, padding * 2, padding, padding / 2)
129+
}
130+
object : RecyclerView.ViewHolder(view) {}
131+
}
132+
else -> {
133+
val view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false)
134+
val holder = object : RecyclerView.ViewHolder(view) {}
135+
view.setOnClickListener {
136+
val pos = holder.bindingAdapterPosition
137+
if (pos != RecyclerView.NO_POSITION) {
138+
val item = items[pos] as? ListItem.Sample ?: return@setOnClickListener
139+
onItemClick(item.item)
140+
}
141+
}
142+
holder
143+
}
144+
}
145+
}
146+
147+
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
148+
val textView = holder.itemView.findViewById<TextView>(android.R.id.text1)
149+
when (val item = items[position]) {
150+
is ListItem.Header -> textView.text = item.name
151+
is ListItem.Sample -> textView.text = item.item.title
152+
}
153+
}
154+
155+
override fun getItemCount(): Int = items.size
156+
157+
companion object {
158+
private const val VIEW_TYPE_HEADER = 0
159+
private const val VIEW_TYPE_SAMPLE = 1
160+
}
161+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.fresco.samples.showcase
9+
10+
import android.content.Context
11+
import com.facebook.fresco.samples.showcase.misc.ImageUriProvider
12+
import com.facebook.fresco.vito.provider.FrescoVitoProvider
13+
import com.facebook.fresco.vito.tools.liveeditor.ImageSelector
14+
import com.facebook.fresco.vito.tools.liveeditor.ImageTracker
15+
16+
/**
17+
* Provides showcase dependencies without requiring ShowcaseApplication as the Application class.
18+
*/
19+
object ShowcaseProvider {
20+
lateinit var imageUriProvider: ImageUriProvider
21+
private set
22+
23+
lateinit var imageTracker: ImageTracker
24+
private set
25+
26+
lateinit var imageSelector: ImageSelector
27+
private set
28+
29+
fun initIfNeeded(context: Context) {
30+
if (::imageUriProvider.isInitialized) {
31+
return
32+
}
33+
imageUriProvider = ImageUriProvider(context.applicationContext)
34+
imageTracker = ImageTracker()
35+
imageSelector =
36+
ImageSelector(
37+
imageTracker,
38+
FrescoVitoProvider.getImagePipeline(),
39+
FrescoVitoProvider.getController(),
40+
)
41+
}
42+
}

‎samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/imageformat/gif/ImageFormatGifFragment.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ private void setAnimationUri(Uri uri) {
168168
return;
169169
}
170170

171-
final ImageDecodeOptionsBuilder optionsBuilder =
171+
final ImageDecodeOptionsBuilder<?> optionsBuilder =
172172
ImageDecodeOptions.newBuilder().setMaxDimensionPx(4000);
173173

174174
if (mGifDecoder != null) {

0 commit comments

Comments
 (0)