OxyPlot in RecyclerView -MVVMCross Xamarin.Android

删除回忆录丶 提交于 2019-12-23 01:12:45

问题


I have the following implementation where I have recycler view, in each view I am trying to display a data using OxyPlot.

I could able to see hard coded Plotvalues on the each card, but when I scroll, it is kind of a slow response and app freezes a while. I wonder what I am doing wrong or how to improve this performance issue?

MainView.xml

<MvxRecyclerView
  android:id="@+id/myRecyclerView"
  android:layout_marginTop="10dp"
  android:scrollbars="vertical"
  android:divider="@null"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  local:MvxItemTemplate="@layout/mycardview" />

mycardview.xml

<RelativeLayout
    android:layout_width="200dp"
    android:layout_height="match_parent">
    <oxyplot.xamarin.android.PlotView
       android:id="@+id/Plot"
       android:layout_width="match_parent"
       android:layout_height="match_parent" /> 
</RelativeLayout>

MainView.cs

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{ 
   var ignored = base.OnCreateView(inflater, container, savedInstanceState);
   var view = this.BindingInflate(Resource.Layout.MainView, null);
   HasOptionsMenu = true;
   var cardRecyclerView = view.FindViewById<MvxRecyclerView>(Resource.Id.myRecyclerView);
   if (cardRecyclerView != null)
   {
       cardRecyclerView.HasFixedSize = false;
       cardRecyclerView .Adapter = new MainViewRecyclerAdapter((IMvxAndroidBindingContext)BindingContext, Activity);
       var layoutManager = new LinearLayoutManager(Activity);
       cardRecyclerView.SetLayoutManager(layoutManager);
    }

  return view;
}

MainViewRecyclerAdapter .cs

public class MainViewRecyclerAdapter : MvxRecyclerAdapter
{

  private readonly FragmentActivity _activity;
  public MainViewRecyclerAdapter(IMvxAndroidBindingContext bindingContext, FragmentActivity activity)
        : base(bindingContext)
  {
      _activity = activity;
  }

  public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
  {
      base.OnBindViewHolder(holder, position);

      var view = holder.ItemView;
      var cardOptionsButton = view.FindViewById<PlotView>(Resource.Id.Plot);
      MainViewModel MyMainViewModel = new MainViewModel();
      cardOptionsButton.Model = MyMainViewModel.MyModel;
   }
}

MyMainViewModel.cs

public class MyViewModel : MvxViewModel
{
    public MyViewModel()
    {
        GeneratePlotPoints();
    }

    void GeneratePlotPoints()
    {
        var mo = new PlotModel();
        var s1 = new LineSeries()
        {
            Color = OxyColors.SkyBlue,
            MarkerType = MarkerType.Circle,
            MarkerSize = 6,
            MarkerStroke = OxyColors.White,
            MarkerFill = OxyColors.SkyBlue,
            MarkerStrokeThickness = 1.5
        };
        s1.Points.Add(new DataPoint(0, 10));
        s1.Points.Add(new DataPoint(10, 40));
        s1.Points.Add(new DataPoint(40, 20));
        s1.Points.Add(new DataPoint(60, 30));
        mo.Series.Add(s1);
        MyModel = mo;
    }

    PlotModel _myModel;
    public PlotModel MyModel
    {
        get { return _myModel; }
        set { SetProperty(ref _myModel, value); }
    }
}

回答1:


I was not able to get your example from the question to work. However, what you can try is to use binding for the data (Plot points) to your layout, rather than re-constructing your ViewModel as a standard class object in your Adapter.


Implementation Example:

ViewModel

For simplicity I have just created a simple ObservableCollection which contains the same groups of plot points (graph shape) repeated a few times. UPDATE: As a PlotModel can only be used once in an PlotView you have to make sure that PlotModel is always a new instance.

public class MyViewModel : BaseViewModel
{
    PlotModel GeneratePlotPoints()
    {
        var mo = new PlotModel();
        var s1 = new LineSeries()
        {
            Color = OxyColors.SkyBlue,
            MarkerType = MarkerType.Circle,
            MarkerSize = 6,
            MarkerStroke = OxyColors.White,
            MarkerFill = OxyColors.SkyBlue,
            MarkerStrokeThickness = 1.5
        };

        s1.Points.Add(new DataPoint(0, 10));
        s1.Points.Add(new DataPoint(10, 40));
        s1.Points.Add(new DataPoint(40, 20));
        s1.Points.Add(new DataPoint(60, 30));
        mo.Series.Add(s1);

        return mo;
    }

    List<PlotModel> GenerateGraph()
    {
        var graphPlots = new List<PlotModel>();
        int counter = 0;

        while (counter < 10)
        {
            graphPlots.Add(GeneratePlotPoints());
            counter++;
        }

        return graphPlots;
    }

    public List<PlotModel> GraphPlots => GenerateGraph();
}

Layout

Your main layout with the RecyclerView.

<MvxRecyclerView
    android:id="@+id/myRecyclerView"
    android:layout_marginTop="10dp"
    android:scrollbars="vertical"
    android:divider="@null"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    local:MvxBind="ItemsSource GraphPlots"
    local:MvxItemTemplate="@layout/mycardview" />

The mycardview layout template. Note that the use of the point is used to tell Mvx to bind to the whole model (in this case the PlotModel) but it also can be left blank (Mvx doc link).

<?xml version="1.0" encoding="utf-8" ?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <oxyplot.xamarin.android.PlotView
     android:id="@+id/Plot"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     local:MvxBind="Model ."/>
</RelativeLayout>

View

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{ 
   var ignored = base.OnCreateView(inflater, container, savedInstanceState);
   var view = this.BindingInflate(Resource.Layout.MainView, null);
   HasOptionsMenu = true;
   var cardRecyclerView = view.FindViewById<MvxRecyclerView>(Resource.Id.myRecyclerView);
   if (cardRecyclerView != null)
   {
       cardRecyclerView.HasFixedSize = false;
       var layoutManager = new LinearLayoutManager(Activity);
       cardRecyclerView.SetLayoutManager(layoutManager);
    }

    return view;
}

Update - Include screenshot



来源:https://stackoverflow.com/questions/38332858/oxyplot-in-recyclerview-mvvmcross-xamarin-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!