mik*_*e_t 7 android android-jetpack-compose
很可能是一个新手问题,因为我对 Android 开发相当陌生 - 我在配置更改/导航时在 @Composable 中保留 AndroidView 的状态时遇到麻烦,因为工厂块被调用(如预期)并且我的图表被重新实例化。
@Composable
fun ChartView(viewModel:ViewModel, modifier:Modifier){
val context = LocalContext.current
val chart = remember { DataChart(context) }
AndroidView(
modifier = modifier,
factory = { context ->
Log.d("DEBUGLOG", "chart init")
chart
},
update = { chart ->
Log.d("DEBUGLOG", "chart update")
})
}
Run Code Online (Sandbox Code Playgroud)
这DataChart是一个带有复杂图表的第三方组件,我想保留缩放/滚动状态。我知道我可以使用 ViewModel 来保留 conf 中的 UI 状态。更改,但考虑到保存缩放/滚动状态的复杂性,我想问是否有其他更简单的方法来实现这一点?
我尝试将整个图表实例移动到 viewModel,但由于它使用上下文,我收到有关上下文对象泄漏的警告。
任何帮助,将不胜感激!
我想说,将图表实例移动到视图模型中的直觉是正确的,但是,正如您所指出的,当视图以外的对象需要上下文依赖关系时,它们可能会变得麻烦。对我来说,这变成了依赖注入的问题,其中依赖是上下文,或者从更广泛的意义上来说,是整个数据图表。我有兴趣知道如何获取视图模型,但我假设它依赖于 Android 视图模型提供程序(通过by viewModels()或某种方式ViewModelProvider.Factory)。
此问题的直接解决方案是将视图模型转换为 的子类,该子类AndroidViewModel通过视图模型的构造函数提供对应用程序上下文的引用。虽然它仍然是一种反模式并且应该谨慎使用,但 Android 团队已经认识到某些用例是有效的。我个人不使用它,AndroidViewModel因为我相信它是一个问题的粗略解决方案,否则可以通过依赖关系图的改进来解决。不过,这是官方文档认可的,这只是我个人的意见。根据经验,我必须说它的使用使得事后测试视图模型成为一场噩梦。如果您对依赖注入库感兴趣,我强烈推荐新的实现,该实现最近在上个月Hilt发布了稳定版本。1.0.0
除此之外,我现在将为您的困境提供两种可能的解决方案:一种使用AndroidViewModel,另一种不使用。如果您的视图模型已经具有上下文之外的其他依赖项,则该AndroidViewModel解决方案不会为您节省太多开销,因为您可能已经ViewModelProvider.Factory在某个时刻实例化了 a 。这些解决方案将考虑 Android 的范围,但可以通过对生命周期挂钩等进行一些调整来Fragment轻松实现。ActivityDialogFragment
和AndroidViewModel
import android.app.Application
import androidx.lifecycle.AndroidViewModel
class MyViewModel(application: Application) : AndroidViewModel(application) {
val dataChart: DataChart
init {
dataChart = DataChart(application.applicationContext)
}
}
Run Code Online (Sandbox Code Playgroud)
片段可能在哪里
class MyFragment : Fragment() {
private val viewModel: MyViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View { ... }
}
Run Code Online (Sandbox Code Playgroud)
没有AndroidViewModel
import androidx.lifecycle.ViewModel
class MyViewModel(args: Args) : ViewModel() {
data class Args(
val dataChart: DataChart
)
val dataChart: DataChart = args.dataChart
}
Run Code Online (Sandbox Code Playgroud)
片段可能在哪里
class MyFragment : Fragment() {
private lateinit var viewModel: MyViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val applicationContext: Context = requireContext().applicationContext
val dataChart = DataChart(applicationContext)
val viewModel: MyViewModel by viewModels {
ArgsViewModelFactory(
args = MyViewModel.Args(
dataChart = dataChart,
),
argsClass = MyViewModel.Args::class.java,
)
}
this.viewModel = viewModel
...
}
}
Run Code Online (Sandbox Code Playgroud)
ArgsViewModelFactory我自己的创作在哪里,如下所示
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
class ArgsViewModelFactory<T>(
private val args: T,
private val argsClass: Class<T>,
) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T = modelClass.getConstructor(
argsClass,
).newInstance(
args,
)
}
Run Code Online (Sandbox Code Playgroud)
编辑(通过 Hilt 模块):
@Module
@InstallIn(...)
object DataChartModule {
@Provides
fun provideDataChart(
@ApplicationContext context: Context,
): DataChart = DataChart(context)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6000 次 |
| 最近记录: |