Sci-Chart с использованием Dagger2 для обновления графика в Android - PullRequest
1 голос
/ 02 марта 2020

Я строю приложение на основе арки. MVVM + привязка данных для графических данных в реальном времени. Использование Sci-диаграммы было быстрым и простым, но попытка обновить приложение с помощью DI с помощью Dagger2 приводит к созданию нулевых экземпляров построителя Sci-диаграммы при попытке обновить график с помощью SuspendUpdates (). Интерфейс ISuspendable уже связан через @Binds в ViewModelModule.

@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 для доступа к нему в ViewModel? Буду признателен за любую помощь.

Извинения за неправильную литературу.

С уважением, PK

1 Ответ

2 голосов
/ 03 марта 2020

Я думаю, что передача SciChartSurface, который является Android View во ViewModel, нарушит принципы паттерна MVVM.

Как я вижу из XML, вы храните RenderableSeries в вашей ViewModel. Я бы посоветовал вам приостановить обновления для экземпляра RenderableSeries, связанного с DataSeries, который вам нужно обновить:

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, и вы сохраните свой вид слой отделен от ViewModel

...