1

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); }
    }
}
casillas
  • 16,351
  • 19
  • 115
  • 215
  • What does your "sAll" list look like in your ViewModel? You should just be able to use XML binding simliar to https://stackoverflow.com/questions/38316666/binding-oxyplot-via-mvvmcross-in-xamarin-android/38336559#38336559, but based off of the model from your list. – Plac3Hold3r Jul 12 '16 at 18:43
  • I have updated my question with working example, but now I have performance issue. When I put each plot on each card and scroll them, it is slow. I wonder where I am doing wrong? – casillas Jul 12 '16 at 19:17

1 Answers1

3

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

enter image description here

Plac3Hold3r
  • 5,062
  • 1
  • 16
  • 21
  • Thanks a lot for all the effort and furthermore for crystal clear explanation. – casillas Jul 12 '16 at 21:07
  • 1
    No problem, glad it helped. – Plac3Hold3r Jul 12 '16 at 21:10
  • @Placeholder, I have just got a chance to test your solution but for some reason nothing shows up. Have you tested? – casillas Jul 20 '16 at 01:28
  • It seems to me that `local:MvxBind="Model ."` is not working. did you add `Custom Bindings` ? If yes, could you please also include it? – casillas Jul 20 '16 at 01:45
  • nope, there is no custom binding, `Model` is the model property on the `PlotView` control. Are you perhaps trying to bind to something other than a `PlotModel`? Are there perhaps issues in the output window? – Plac3Hold3r Jul 20 '16 at 14:02
  • Have you run the solution and able to see the plots? I could able to see `GraphPlots` have 10 items and I properly declared the layout template in the resources/layout folder, as as you suggested I did not use `RecyclerAdapter`. I exactly copied your solution but no luck. – casillas Jul 20 '16 at 14:13
  • I have updated post to show screenshot of graphs. Are you getting any errors/warnings in the output window? – Plac3Hold3r Jul 20 '16 at 16:31
  • is it possible to share your solution please, like github? I have redone everything still no luck. – casillas Jul 20 '16 at 18:53
  • 1
    @hotspring, you can check out the [GitHub sample](https://github.com/Plac3hold3r/OxyPlotMvxExample), the OxyPlot stuff can be found in the HelpAndFeedback section. Hope it helps. – Plac3Hold3r Jul 23 '16 at 11:08
  • That is awesome and I have figure out the root of my issue. – casillas Jul 25 '16 at 23:05
  • When I have a fragment on the top of the plot activity and when I click back button, the plot does not show anything. do you have anything in your mind? – casillas Jul 27 '16 at 23:59
  • @hotspring, check out the updated [GitHub sample](https://github.com/Plac3hold3r/OxyPlotMvxExample). Was getting ["This PlotModel is already in use by some other PlotView control"](https://github.com/oxyplot/oxyplot/pull/780) in output window. It relates to a [plot model](https://github.com/oxyplot/oxyplot/blob/develop/Source/OxyPlot/PlotModel/PlotModel.cs#L785) having a 1 to 1 relationship with the plot view. So we have to create a new model each time. – Plac3Hold3r Jul 29 '16 at 20:13
  • Could you please let me know the changes in your recent github.? I could not able to find in the github history. – casillas Aug 02 '16 at 20:32