我正在基于Arch构建一个应用。 MVVM + Databinding用于实时图形数据。使用Sci-chart既快捷又容易,但是尝试使用Dagger2用DI更新应用程序时,在尝试使用SuspendUpdates()更新图时会生成sci-chart构建器实例为null。已通过ViewModelModule中的@Binds绑定了ISuspendable接口。
@Module
abstract class ViewModelModule {
@Singleton
@Binds
abstract fun getSuspendable(aSuspendable: AccurynSuspendableImpl): ISuspendable
@Binds
@IntoMap
@ViewModelKey(AViewModel::class)
abstract fun bindAViewModel(aViewModel: AViewModel): ViewModel
@Binds
internal abstract fun bindViewModelFactory(factory: AppViewModelFactory): ViewModelProvider.Factory
}
@Singleton
class AccurynSuspendableImpl @Inject constructor() : ISuspendable {
override fun decrementSuspend() {
}
override fun suspendUpdates(): IUpdateSuspender? {
return null
}
override fun getIsSuspended(): Boolean {
return true
}
override fun resumeUpdates(p0: IUpdateSuspender?) {
}
}
class AMFragment : Fragment() {
private val acmVM by viewModel<AViewModel>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mBinding = binding(inflater, R.layout.display, container)
mBinding.viewModel = acmVM
mBinding.lifecycleOwner = this
mBinding.executePendingBindings()
return mBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initializeVM()
}
private fun initializeVM() {
**//TODO: how to bind these xml feature through dagger ahead of time.**
/*acmVM = AViewModel(
mBinding.multiPaneChart.iChart,
mBinding.multiPaneChart.uChart)*/
}
}
class AViewModel @Inject constructor(
private val iSusp: ISuspendable,
private val uSusp: ISuspendable,
) : BaseViewModel() {....
var iRenderDataSeries = XyDataSeries<Date, Float>().apply {
fifoCapacity = FIFO_CAPACITY }
var uColumnDataSeries = XyDataSeries<Date, Float>().apply {
fifoCapacity = FIFO_CAPACITY }
var uLineDataSeries = XyDataSeries<Date, Float>().apply {
fifoCapacity = FIFO_CAPACITY }
private val iColor = ContextCompat.getColor(mContext,
R.color.pink)
private val uColumnColor = ContextCompat.getColor(mContext,
R.color.yellow)
private val uLineColor = ContextCompat.getColor(mContext,
R.color.gray)
val xIAxes = AxisCollection()
val xUAxes = AxisCollection()
val yIAxes = AxisCollection()
val yUAxes = AxisCollection()
val iRenderableSeries = RenderableSeriesCollection()
val uRenderableSeries = RenderableSeriesCollection()
private var iChartModifiers = ChartModifierCollection()
private var uChartModifiers = ChartModifierCollection()
init {
initChartDisplay(context)
}
private fun initChartDisplay(context: Context) {
xIAxes.add(generateXAxis(context, View.GONE,
AxisAlignment.Auto))
xUAxes.add(generateXAxis(context, View.VISIBLE,
AxisAlignment.Top))
yIAxes.add(generateYAxis(context, LABEL_ID_I))
yUAxes.add(generateYAxis(context, LABEL_ID_U))
iRenderableSeries.add(
generateLineRenderableSeries(
LABEL_ID_I, iRenderDataSeries, SolidPenStyle(iColor,
true, lineThickness, null)
)
)
val uColumnSeries =
generateColumnRenderableSeries(LABEL_ID_U,
uColumnDataSeries, SolidBrushStyle(uColumnColor))
uColumnSeries.dataPointWidth = .95
uRenderableSeries.add(uColumnSeries)
uRenderableSeries.add(
generateLineRenderableSeries(
LABEL_ID_U, uLineDataSeries, SolidPenStyle(uLineColor,
true, lineThickness, null)
)
)
}
private fun loadData() {
UpdateSuspender.using(iSusp) {
iRenderDataSeries.append(Date(lastTimeStamp),
median)
}
}
**--Based on certain condition need to update line and column
UpdateSuspender.using(uRenderableSeries.single()) {
uColumnDataSeries.updateYAt(uCurIndex, hourlyTotal)
//hour is a current one. We're going to update with the latest
// total for the hour
}
**-- whereas on other condition update line series over same
renderable series
UpdateSuspender.using(uRenderableSeries.single()) {
if (priorTimeStamp + GRAPH_CALC_GAP_CONSTANT <
lastTimeStamp)
{
UpdateSuspender.using(uRenderableSeries.single()) {
uLineDataSeries.append(Date(priorTimeStamp +
GRAPH_DISPLAY_GAP_CONSTANT), Float.NaN)
}
}
//line data series updates
uLineDataSeries.append(
Date(DateTimeUtils.toEpochMilli(mData.getRtcTimeStamp())),
mData.uRate.toFloat()
)
}
}
XML:
<com.xyz.widgets.ASciChart
android:id="@+id/u_chart"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="@{graphViewModel.displayChartU ?
View.VISIBLE : View.GONE}"
scichart:verticalGroup="@{graphViewModel.sharedVG}"
scichart:renderableSeries="@{graphViewModel.uRenderableSeries}"
scichart:xAxes="@{graphViewModel.xUAxes}"
scichart:yAxes="@{graphViewModel.yUAxes}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.xyz.widgets.ASciChart
android:id="@+id/i_chart"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="@{graphViewModel.displayChartI ?
View.VISIBLE : View.GONE}"
scichart:verticalGroup="@{graphViewModel.sharedVG}"
scichart:renderableSeries="@{graphViewModel.iRenderableSeries}"
scichart:xAxes="@{graphViewModel.xIAxes}"
scichart:yAxes="@{graphViewModel.yIAxes}"/>
如何在dagger2中绑定此sci图表实例以在ViewModel中访问它?任何帮助,将不胜感激。
对错误文献的道歉。
关于,PK
[我认为,将Android View的SciChartSurface传递到ViewModel会违反MVVM模式的原则。
正如我从XML中看到的,您将RenderableSeries存储在ViewModel中。我建议您在与需要更新的DataSeries关联的RenderableSeries实例上暂停更新:
private fun loadData() {
// I assume you have only one renderable series in collection
val renderableSeries = iRenderableSeries.single()
UpdateSuspender.using(renderableSeries) {
iRenderDataSeries.append(Date(lastTimeStamp), median)
}
}
在这种情况下,您无需将SciChartSurface传递到ViewModel中,并且将View层与ViewModel分开