Skip to content

Commit

Permalink
Improvement for deferred configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
p-lr committed Oct 10, 2019
1 parent 9f581f8 commit da5066c
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 40 deletions.
4 changes: 2 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[ ![Download](https://api.bintray.com/packages/peterlaurence/maven/mapview/images/download.svg?version=1.0.2) ](https://bintray.com/peterlaurence/maven/mapview/1.0.2/link)
[ ![Download](https://api.bintray.com/packages/peterlaurence/maven/mapview/images/download.svg?version=1.0.3) ](https://bintray.com/peterlaurence/maven/mapview/1.0.3/link)

# MapView

Expand Down Expand Up @@ -29,7 +29,7 @@ This project holds the source code of this library, but also a demo app (which i

Add this to your module's build.gradle
```groovy
implementation 'com.peterlaurence:mapview:1.0.2'
implementation 'com.peterlaurence:mapview:1.0.3'
```

## Origin and motivation
Expand Down
62 changes: 26 additions & 36 deletions demo/src/main/java/com/peterlaurence/mapview/demo/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import com.google.android.material.navigation.NavigationView
import com.peterlaurence.mapview.demo.fragments.DeferredFragment
import com.peterlaurence.mapview.demo.fragments.MapAloneFragment
import com.peterlaurence.mapview.demo.fragments.MapMarkersFragment
import com.peterlaurence.mapview.demo.fragments.MapPathFragment

class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
private val fragmentTags = listOf(MAP_ALONE_TAG, MAP_MARKERS_TAG, MAP_PATHS_TAG)
private val fragmentTags = listOf(MAP_ALONE_TAG, MAP_MARKERS_TAG, MAP_PATHS_TAG, MAP_DEFERRED_TAG)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -28,7 +29,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val toggle = ActionBarDrawerToggle(
this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close
this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close
)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
Expand All @@ -51,66 +52,54 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
}

override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
when (item.itemId) {
R.id.nav_map_alone -> {
showMapAloneFragment()
}
R.id.nav_map_markers -> {
showMapMarkersFragment()
}
R.id.nav_map_paths -> {
showMapPathsFragment()
}
R.id.nav_map_alone -> showMapAloneFragment()
R.id.nav_map_markers -> showMapMarkersFragment()
R.id.nav_map_paths -> showMapPathsFragment()
R.id.nav_map_deferred_configuration -> showDeferredConfigurationFragment()
}
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
drawerLayout.closeDrawer(GravityCompat.START)
return true
}

private fun showMapAloneFragment() {
showFragment(MAP_ALONE_TAG) {
createMapAloneFragment(it)
showFragment(MAP_ALONE_TAG) { tr, tag ->
createFragment(tr, MapAloneFragment::class.java, tag)
}
}

private fun showMapMarkersFragment() {
showFragment(MAP_MARKERS_TAG) {
createMapMarkersFragment(it)
showFragment(MAP_MARKERS_TAG) { tr, tag ->
createFragment(tr, MapMarkersFragment::class.java, tag)
}
}

private fun showMapPathsFragment() {
showFragment(MAP_PATHS_TAG) {
createMapPathsFragment(it)
showFragment(MAP_PATHS_TAG) { tr, tag ->
createFragment(tr, MapPathFragment::class.java, tag)
}
}

private fun showDeferredConfigurationFragment() {
showFragment(MAP_DEFERRED_TAG) { tr, tag ->
createFragment(tr, DeferredFragment::class.java, tag)
}
}

private fun showFragment(tag: String, onCreate: (t: FragmentTransaction) -> Fragment) {
private fun showFragment(tag: String, onCreate: (t: FragmentTransaction, tag: String) -> Fragment) {
val transaction = supportFragmentManager.beginTransaction()
removeFragments(tag)
hideWelcomeMsg()
val fragment = supportFragmentManager.findFragmentByTag(tag) ?: onCreate(transaction)
val fragment = supportFragmentManager.findFragmentByTag(tag) ?: onCreate(transaction, tag)
transaction.show(fragment)
transaction.commit()
}

private fun createMapAloneFragment(transaction: FragmentTransaction): Fragment {
val fragment = MapAloneFragment()
transaction.add(R.id.content_frame, fragment, MAP_ALONE_TAG)
return fragment
}

private fun createMapMarkersFragment(transaction: FragmentTransaction): Fragment {
val fragment = MapMarkersFragment()
transaction.add(R.id.content_frame, fragment, MAP_MARKERS_TAG)
return fragment
}

private fun createMapPathsFragment(transaction: FragmentTransaction): Fragment {
val fragment = MapPathFragment()
transaction.add(R.id.content_frame, fragment, MAP_PATHS_TAG)
return fragment
private fun <T : Fragment> createFragment(transaction: FragmentTransaction, clazz: Class<T>, tag: String): Fragment {
val f = clazz.newInstance()
transaction.add(R.id.content_frame, f, tag)
return f
}

private fun removeFragments(tagExcept: String) {
Expand Down Expand Up @@ -138,3 +127,4 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
const val MAP_ALONE_TAG = "map_alone"
const val MAP_MARKERS_TAG = "map_markers"
const val MAP_PATHS_TAG = "map_paths"
const val MAP_DEFERRED_TAG = "map_deferred"
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.peterlaurence.mapview.demo.fragments


import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.peterlaurence.mapview.MapView
import com.peterlaurence.mapview.MapViewConfiguration
import com.peterlaurence.mapview.core.TileStreamProvider
import com.peterlaurence.mapview.demo.R
import kotlinx.coroutines.*
import java.io.InputStream
import kotlin.coroutines.CoroutineContext

/**
* An example showing deferred configuration of [MapView]. In this example, a [MapView] is first
* added to the view hierarchy, then a few moment later it's configured.
*
* It demonstrates that the [MapView] configuration can be done later (when all necessary data is
* gathered). It's important since the Android framework requires a view to be added inside the
* [onCreateView] lifecycle callback to have its state saved and restored upon device rotation.
* But inside [onCreateView] we may not have (yet) all information needed to call [MapView.configure].
*/
class DeferredFragment : Fragment(), CoroutineScope {

private lateinit var mapView: MapView
private lateinit var parentView: ViewGroup
private var job: Job? = null

override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + Job().also { job = it }

/**
* The [MapView] should always be added inside [onCreateView], to ensure state save/restore.
*/
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_layout, container, false).also {
parentView = it as ViewGroup
context?.let { ctx ->
MapView(ctx).addToFragment()
}
}
}

/**
* Assign an id the the [MapView] (it's necessary to enable state save/restore).
* And keep a ref on the [MapView]
*/
private fun MapView.addToFragment() {
this@DeferredFragment.mapView = this

mapView.id = R.id.mapview_id
mapView.isSaveEnabled = true

parentView.addView(mapView, 0)
}

/**
* In this example, the configuration isn't done **immediately** after the [MapView] is added to
* the view hierarchy, in [onCreateView]. It's done in [onStart].
* But it's not mandatory, it could have been done right after the [MapView] creation.
*/
override fun onStart() {
super.onStart()

val tileStreamProvider = object : TileStreamProvider {
override fun getTileStream(row: Int, col: Int, zoomLvl: Int): InputStream? {
return try {
context?.assets?.open("tiles/esp/$zoomLvl/$row/$col.jpg")
} catch (e: Exception) {
null
}
}
}
val tileSize = 256
val config = MapViewConfiguration(
5, 8192, 8192, tileSize, tileStreamProvider
).setMaxScale(2f).setPadding(tileSize * 2)

launch {
delay(500) // simulate delay
mapView.configure(config)
}
}

override fun onStop() {
super.onStop()

job?.cancel()
}
}
4 changes: 4 additions & 0 deletions demo/src/main/res/menu/activity_main_drawer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
<item
android:id="@+id/nav_map_paths"
android:title="@string/map_paths"/>

<item
android:id="@+id/nav_map_deferred_configuration"
android:title="@string/map_deferred_configuration"/>
</group>

</menu>
3 changes: 2 additions & 1 deletion demo/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title">MapView</string>
<string name="nav_header_subtitle">android.studio@android.com</string>
<string name="nav_header_subtitle">https://github.com/peterLaurence</string>
<string name="nav_header_desc">Navigation header</string>
<string name="welcome">Welcome to MapView demo.\nUse the lateral menu to select between available demo.</string>

<string name="map_alone">Map demo</string>
<string name="map_markers">Map and markers demo</string>
<string name="map_paths">Map paths demo</string>
<string name="map_deferred_configuration">Deferred config demo</string>
</resources>
2 changes: 1 addition & 1 deletion mapview/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlinx-serialization'

def version = "1.0.2"
def version = "1.0.3"

androidExtensions {
experimental = true
Expand Down
5 changes: 5 additions & 0 deletions mapview/src/main/java/com/peterlaurence/mapview/MapView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ class MapView @JvmOverloads constructor(context: Context, attrs: AttributeSet? =
savedState?.let {
restoreState(it)
}

/* Since various events that trigger a render (scale and layout change) may not happen right
* after the configuration, ask for a first render explicitly.
*/
renderVisibleTilesThrottled()
}

/**
Expand Down

0 comments on commit da5066c

Please sign in to comment.