1 /*
<lambda>null2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.navigation
18 
19 import android.annotation.SuppressLint
20 import androidx.collection.ArrayMap
21 import androidx.savedstate.SavedState
22 import java.lang.reflect.Method
23 import kotlin.reflect.KClass
24 
25 internal val methodSignature = arrayOf(SavedState::class.java)
26 internal val methodMap = ArrayMap<KClass<out NavArgs>, Method>()
27 
28 /**
29  * An implementation of [Lazy] used by [android.app.Activity.navArgs] and
30  * [androidx.fragment.app.Fragment.navArgs].
31  *
32  * [argumentProducer] is a lambda that will be called during initialization to provide arguments to
33  * construct an [Args] instance via reflection.
34  */
35 public class NavArgsLazy<Args : NavArgs>(
36     private val navArgsClass: KClass<Args>,
37     private val argumentProducer: () -> SavedState
38 ) : Lazy<Args> {
39     private var cached: Args? = null
40 
41     override val value: Args
42         get() {
43             var args = cached
44             if (args == null) {
45                 val arguments = argumentProducer()
46                 val method: Method =
47                     methodMap[navArgsClass]
48                         ?: navArgsClass.java.getMethod("fromBundle", *methodSignature).also { method
49                             ->
50                             // Save a reference to the method
51                             methodMap[navArgsClass] = method
52                         }
53 
54                 @SuppressLint("BanUncheckedReflection") // needed for method.invoke
55                 @Suppress("UNCHECKED_CAST")
56                 args = method.invoke(null, arguments) as Args
57                 cached = args
58             }
59             return args
60         }
61 
62     override fun isInitialized(): Boolean = cached != null
63 }
64