如何在RecylerView中有效使用AndroidPlot?

时间:2018-02-08 13:26:17

标签: android performance android-recyclerview android-viewholder androidplot

我遇到了以下问题,

在RecyclerView中使用AndroidPlot XYPlot时。

像这样的AndroidPlot:

<com.androidplot.xy.XYPlot
android:id="@+id/mPlot"
style="@style/APDefacto.Light"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
androidplot.renderMode="use_background_thread"
android:visibility="visible"
ap:lineLabels="left"
android:minHeight="100dp" />

最重要的是renderMode =“use_background_thread” 设置Plot应该在后台线程中绘制。

我必须将ViewHolder设置为不是RecycleAble

ViewHolder vh = new ViewHolder(v,parentContext);
vh.setIsRecyclable(true);

因为当仅绑定RecyclerView时,Plot变为灰色。 原因是存在问题,回想起用于绘制元素的背景线程。 通过将Viewholders设置为不可循环使用,每次新项目进入Focus时,都会创建一个新的ViewHolder。不是很有效,我比使用不带Backgroud_Thread的Plots更快。 Link to my previous post

然后没有背景线程滚动真的停滞不前并且不是很漂亮。

Stack-Trace:

java.lang.IllegalThreadStateException: Thread already started                                                             
at java.lang.Thread.checkNotStarted(Thread.java:849)                                                                               
at java.lang.Thread.start(Thread.java:1059)                                                                               
at com.androidplot.Plot.onSizeChanged(Plot.java:780)                                                                               
at android.view.View.sizeChange(View.java:16748)                                                                               
at android.view.View.setFrame(View.java:16710)                                                                               
at android.view.View.layout(View.java:16627)                                                                               
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)                                                                      
at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1732)                                                                               
at android.widget.LinearLayout.onLayout(LinearLayout.java:1497)                                                                               
at android.view.View.layout(View.java:16630)                                                                               
at android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                               
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)                                                                               
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)                                                                               
at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)                                                                               
at android.view.View.layout(View.java:16630)                                                                               
at android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                               
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)                                                                               
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)                                                                              
at android.view.View.layout(View.java:16630)                                                                               
at android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                               
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)                                                                               
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)                                                                               
at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)                                                                               
at android.view.View.layout(View.java:16630)                                                                               
at android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                               
at android.support.v7.widget.RecyclerView$LayoutManager.layoutDecoratedWithMargins(RecyclerView.java:8968)                                                                               
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1614)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1516)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:608)                                                                               
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3693)                                                                               
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3410)                                                                               
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3962)                                                                               
at android.view.View.layout(View.java:16630)                                                                               
at android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                               
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)                                                                               
at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1732)                                                                               
at android.widget.LinearLayout.onLayout(LinearLayout.java:1497)                                                                               
at android.view.View.layout(View.java:16630)                                                                               
at android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                               
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)                                                                               
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)                                                                               
at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)                                                                               
at android.view.View.layout(View.java:16630)                                                                               
at android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                               
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)                                                                               
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)                                                                               
at android.view.View.layout(View.java:16630)                                                                               
at android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                              
at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:443)                                                                               
at android.view.View.layout(View.java:16630)                                                                               
at android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                               
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)                                                                               
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)                                                                               
at android.view.View.layout(View.java:16630)                                                                               
at android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                               
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)                                                                               
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)                                                                               
at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)                                                                               
at android.view.View.layout(View.java:16630)                                                                               
at android.view.ViewGroup.layout(ViewGroup.java:5437)                                                                               
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)                                                                               
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)                                                                            
at com.android.internal.policy.PhoneWi

感谢您的帮助,

弗兰西

1 个答案:

答案 0 :(得分:1)

Androidplot演示应用程序具有listview example,演示如何完成此任务。 (在这个级别上RecyclerView并没有什么特别的或不同的。)我修改了代码以使用RecyclerView代替并获得了非常平滑的结果,即使在模拟器上也没有背景线程(请记住这是低帧率gif):

enter image description here

可能需要了解更多关于系列数据的大小。根据数据的密集程度,有时需要采样。

FWIW,这是修改后的listview演示活动的来源:

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.androidplot.Plot;
import com.androidplot.ui.SeriesBundle;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.CatmullRomInterpolator;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYSeries;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class RecyclerViewActivity extends Activity {
    private static final int NUM_PLOTS = 10;
    private static final int NUM_POINTS_PER_SERIES = 10;
    private static final int NUM_SERIES_PER_PLOT = 5;
    private RecyclerView recyclerView;


    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.recyclerview_example);
        PixelUtils.init(this);
        generateData();
        recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);
        recyclerView.setAdapter(new MyRecyclerViewAdapter(generateData()));
    }

    static class PlotViewHolder extends RecyclerView.ViewHolder {

        private Plot plot;

        public PlotViewHolder(View itemView) {
            super(itemView);
            this.plot = itemView.findViewById(R.id.xyplot);
        }

        public void bind(List<SeriesBundle<XYSeries, LineAndPointFormatter>> seriesBundles, String title) {
            plot.clear();
            plot.getTitle().setText(title);

            for(SeriesBundle<XYSeries, LineAndPointFormatter> bundle : seriesBundles) {
                plot.addSeries(bundle.getSeries(), bundle.getFormatter());
            }
            plot.redraw();
        }
    }

    static class MyRecyclerViewAdapter extends RecyclerView.Adapter<PlotViewHolder> {
        private List<List<SeriesBundle<XYSeries, LineAndPointFormatter>>> seriesData;
        public MyRecyclerViewAdapter(List<List<SeriesBundle<XYSeries, LineAndPointFormatter>>> seriesData) {
            this.seriesData = seriesData;
        }

        @NonNull
        @Override
        public PlotViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View item = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.listview_example_item, parent, false);
            return new PlotViewHolder(item);
        }

        @Override
        public void onBindViewHolder(@NonNull PlotViewHolder holder, int position) {
            holder.bind(seriesData.get(position), "S" + position);
        }

        @Override
        public int getItemCount() {
            return seriesData.size();
        }
    }

    static List<List<SeriesBundle<XYSeries, LineAndPointFormatter>>> generateData() {
        final List<List<SeriesBundle<XYSeries, LineAndPointFormatter>>> seriesData = new ArrayList<>(NUM_PLOTS);
        final Random generator = new Random();
        for(int i = 0; i < NUM_PLOTS; i++) {
            List<SeriesBundle<XYSeries, LineAndPointFormatter>> seriesList
                    = new ArrayList<>(NUM_SERIES_PER_PLOT);

            for (int k = 0; k < NUM_SERIES_PER_PLOT; k++) {
                ArrayList<Number> nums = new ArrayList<>();
                for (int j = 0; j < NUM_POINTS_PER_SERIES; j++) {
                    nums.add(generator.nextFloat());
                }

                double rl = Math.random();
                double gl = Math.random();
                double bl = Math.random();

                double rp = Math.random();
                double gp = Math.random();
                double bp = Math.random();

                LineAndPointFormatter format = new LineAndPointFormatter(
                        Color.rgb(Double.valueOf(rl * 255).intValue(),
                                Double.valueOf(gl * 255).intValue(), Double.valueOf(bl * 255).intValue()),
                        Color.rgb(Double.valueOf(rp * 255).intValue(),
                                Double.valueOf(gp * 255).intValue(), Double.valueOf(bp * 255).intValue()),
                        null, null);

                // for fun, configure interpolation on the formatter:
                format.setInterpolationParams(
                        new CatmullRomInterpolator.Params(20, CatmullRomInterpolator.Type.Centripetal));

                seriesList.add(new SeriesBundle<XYSeries, LineAndPointFormatter>(
                        new SimpleXYSeries(nums, SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "S" + k),
                        format));
            }
            seriesData.add(seriesList);
        }
        return seriesData;
    }
}