Java 膨胀类时出现二进制XML文件错误

Java 膨胀类时出现二进制XML文件错误,java,android,achartengine,inflate-exception,Java,Android,Achartengine,Inflate Exception,我找不到通货膨胀的原因。询问是否要向我显示其他类或xml。我用的是阿卡汀 06-2509:40:17.889:E/AndroidRuntime(1058):致命异常:main 06-25 09:40:17.889:E/AndroidRuntime(1058):java.lang.RuntimeException:无法启动活动组件信息{com.androsz.electricsleepbeta/com.androsz.electricsleepbeta.app.ReviewSleepActivit

我找不到通货膨胀的原因。询问是否要向我显示其他类或xml。我用的是阿卡汀

06-2509:40:17.889:E/AndroidRuntime(1058):致命异常:main
06-25 09:40:17.889:E/AndroidRuntime(1058):java.lang.RuntimeException:无法启动活动组件信息{com.androsz.electricsleepbeta/com.androsz.electricsleepbeta.app.ReviewSleepActivity}:android.view.InflateException:二进制XML文件行#15:膨胀类com.androsz.electricsleepbeta.widget.SleepChart时出错
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.app.ActivityThread.access$600(ActivityThread.java:130)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.os.Handler.dispatchMessage(Handler.java:99)上
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.os.Looper.loop(Looper.java:137)上
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.app.ActivityThread.main(ActivityThread.java:4745)上
06-25 09:40:17.889:E/AndroidRuntime(1058):位于java.lang.reflect.Method.Invokenactive(本机方法)
06-25 09:40:17.889:E/AndroidRuntime(1058):位于java.lang.reflect.Method.invoke(Method.java:511)
06-25 09:40:17.889:E/AndroidRuntime(1058):在com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
06-25 09:40:17.889:E/AndroidRuntime(1058):在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
06-25 09:40:17.889:E/AndroidRuntime(1058):在dalvik.system.NativeStart.main(本机方法)
06-25 09:40:17.889:E/AndroidRuntime(1058):由以下原因引起:android.view.InflateException:二进制XML文件行#15:com.androsz.electricsleepbeta.widget.SleepChart类膨胀时出错
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.view.LayoutInflater.createView(LayoutInflater.java:613)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:687)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.view.LayoutInflater.rInflate(LayoutInflater.java:749)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.view.LayoutInflater.inflate(LayoutInflater.java:489)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.view.LayoutInflater.inflate(LayoutInflater.java:396)
06-25 09:40:17.889:E/AndroidRuntime(1058):在com.androsz.electricsleepbeta.app.ReviewSleepFragment.onCreateView(ReviewSleepFragment.java:63)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)上
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:570)
06-25 09:40:17.889:E/AndroidRuntime(1058):在com.androsz.electricsleepbeta.app.AnalyticActivity.onStart(AnalyticActivity.java:14)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1163)上
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.app.Activity.performStart(Activity.java:5018)上
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2032)
06-25 09:40:17.889:E/AndroidRuntime(1058):。。。还有11个
06-25 09:40:17.889:E/AndroidRuntime(1058):由以下原因引起:java.lang.reflect.InvocationTargetException
06-25 09:40:17.889:E/AndroidRuntime(1058):位于java.lang.reflect.Constructor.constructNative(本机方法)
06-25 09:40:17.889:E/AndroidRuntime(1058):位于java.lang.reflect.Constructor.newInstance(Constructor.java:417)
06-25 09:40:17.889:E/AndroidRuntime(1058):在android.view.LayoutInflater.createView(LayoutInflater.java:587)
06-25 09:40:17.889:E/AndroidRuntime(1058):。。。还有27个
06-25 09:40:17.889:E/AndroidRuntime(1058):由以下原因引起:java.lang.NullPointerException
06-25 09:40:17.889:E/AndroidRuntime(1058):位于org.achartengine.GraphicalView(GraphicalView.java:149)
06-25 09:40:17.889:E/AndroidRuntime(1058):在com.androsz.electricsleepbeta.widget.SleepChart.(SleepChart.java:92)
06-25 09:40:17.889:E/AndroidRuntime(1058):在com.androsz.electricsleepbeta.widget.SleepChart.(SleepChart.java:73)
06-25 09:40:17.889:E/AndroidRuntime(1058):。。。30多
在哪里

活动_review.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <fragment
        android:id="@+id/fragment_suggestion"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        class="com.androsz.electricsleepbeta.app.SuggestionFragment" >

        <!-- Preview: layout=@layout/fragment_suggestion -->
    </fragment>

    <LinearLayout
        android:id="@+id/fragment_review_sleep"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_above="@id/fragment_suggestion" />

</RelativeLayout>

SleepChart.java并使用AchartEngine库(GraphicalView)。

  public class SleepChart extends GraphicalView 
{
    private static final String TAG = SleepChart.class.getSimpleName();

    /** The default number of X label ticks. */
    private static final int DEFAULT_X_LABEL_TICKS = 5;

    final Context mContext;

    //public int rating;

    private XYMultipleSeriesDataset mDataset;

    private XYMultipleSeriesRenderer mRenderer;

    private int DEFAULT_BOTTOM_MARGIN = 20;
    private int DEFAULT_LEFT_MARGIN = 25;
    private int DEFAULT_TOP_MARGIN = 20;

    int mBackgroundColor;
    int mTextColor;
    int mCalibrationBorderColor;
    int mCalibrationColor;
    int mGridColor;
    int mMovementBorderColor;
    int mMovementColor;
    int mXLabelTicks;
    boolean mSetBackgroundColor;
    boolean mSetGridColor;
    boolean mSetInScroll;
    boolean mSetTextColor;
    boolean mShowGrid;
    boolean mShowLabels;
    boolean mShowLegend;
    boolean mShowTitle = true;

    private String mAxisFormat;

    public final SleepChartData mData;

    int mDefStyle;

    AttributeSet mAttrs;


    public SleepChart(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SleepChart(Context context , AbstractChart chart)
    {
        super(context, chart);

        mContext = context;

        //mAttrs = attrs;
        //mDefStyle = defStyle;
        mData = new SleepChartData(mContext);

        setupData();
    }

    public SleepChart(final Context context, final AttributeSet attrs,
            int defStyle)
    {
        super(context, attrs);

        mContext = context;
        mAttrs = attrs;
        mDefStyle = defStyle;
        mData = new SleepChartData(mContext);

        // Now begin processing attributes
        TypedArray array = mContext.obtainStyledAttributes(mAttrs,
                R.styleable.SleepChart, mDefStyle, 0);

        if (array.hasValue(R.styleable.SleepChart_android_background)) {
            mSetBackgroundColor = true;
            mBackgroundColor = array.getColor(
                    R.styleable.SleepChart_android_background,
                    R.color.background_dark);
        }

        if (array.hasValue(R.styleable.SleepChart_android_textColor)) {
            mSetTextColor = true;
            mTextColor = array
                    .getColor(R.styleable.SleepChart_android_textColor,
                            R.color.text_dark);
        }

        if (array.getBoolean(R.styleable.SleepChart_setScroll, false)) {
            mSetInScroll = true;
        }

        if (array.hasValue(R.styleable.SleepChart_gridAxisColor)) {
            mSetGridColor = true;
            mGridColor = array.getColor(R.styleable.SleepChart_gridAxisColor,
                    R.color.sleepchart_axis);
        }

        mXLabelTicks = array.getInteger(R.styleable.SleepChart_xLabelTicks,
                DEFAULT_X_LABEL_TICKS);

        mMovementColor = array.getColor(R.styleable.SleepChart_movementColor,
                R.color.sleepchart_movement_light);

        mMovementBorderColor = array.getColor(
                R.styleable.SleepChart_movementBorderColor,
                R.color.sleepchart_movement_border_light);

        mCalibrationColor = array.getColor(
                R.styleable.SleepChart_calibrationColor,
                R.color.sleepchart_calibration_light);

        mCalibrationBorderColor = array.getColor(
                R.styleable.SleepChart_calibrationBorderColor,
                R.color.sleepchart_calibration_border_light);

        mShowGrid = array.getBoolean(R.styleable.SleepChart_showGrid, true);

        mShowLabels = array.getBoolean(R.styleable.SleepChart_showLabels, true);
        mShowLegend = array.getBoolean(R.styleable.SleepChart_showLegend, true);
        mShowTitle = array.getBoolean(R.styleable.SleepChart_showTitle, true);

        setupData();
    }

//  @Override
    protected AbstractChart buildChart() 
    {
        Log.d(TAG, "Attempting to build chart.");

        if (mChart != null) {
            Log.w(TAG, "Attempt to build chart when chart already exists.");
            return mChart;
        }

        mDataset = new XYMultipleSeriesDataset();
        mRenderer = new XYMultipleSeriesRenderer();
        // Set initial framing for renderer.
        mRenderer.setYAxisMin(0);
        // Referencing SettingsActivity.MAX_ALARM_SENSITIVITY causes errors in ADT.
        if (isInEditMode()) {
            mRenderer.setYAxisMax(1.0f);
        } else {
            mRenderer.setYAxisMax(SettingsActivity.MAX_ALARM_SENSITIVITY);
        }
        mRenderer.setXAxisMin(System.currentTimeMillis());
        mRenderer.setXAxisMax(System.currentTimeMillis());
        mRenderer.setPanEnabled(false, false);
        mRenderer.setZoomEnabled(false, false);

        TimeChart timeChart = new TimeChart(mDataset, mRenderer);
        timeChart.setDateFormat("h:mm:ss");
        mChart = timeChart;

        return mChart;
    }

    /**
     * Return the calibration level if one is available; otherwise return
     * INVALID_CALIBRATION.
     * 
     * Callers of this method could call hasCalibrationLevel first to determine
     * if information surrounding calibration is available prior to invoking
     * this method.
     */
    public float getCalibrationLevel() {
        return mData.getCalibrationLevel();
    }

    public boolean hasTwoOrMorePoints() {
        return mData.hasTwoOrMorePoints();
    }

    public void reconfigure() {
        if (hasTwoOrMorePoints()) {
            synchronized (mData) {
                final double firstX = mData.getLeftMostTime();
                final double lastX = mData.getRightMostTime();

                mData.setupCalibrationSpan(firstX, lastX);

                mRenderer.setXAxisMin(firstX);
                mRenderer.setXAxisMax(lastX);
            }

            setupChartAxisFormat();
        } else {
            Log.w(TAG,
                    "Asked to reconfigure but it did not make sense to display.");
        }
    }

    public void setCalibrationLevelAndRedraw(final float calibrationLevel) {
        mData.setCalibrationLevel(calibrationLevel);
        reconfigure();
        repaint();
    }

    public void setScroll(boolean scroll) {
        mSetInScroll = scroll;
    }

    public void sync(final Cursor cursor) throws StreamCorruptedException,
            IllegalArgumentException, IOException, ClassNotFoundException {
        Log.d(TAG, "Attempting to sync with cursor: " + cursor);
        this.sync(new SleepSession(cursor));
    }

    public void sync(final Double x, final Double y) {
        Log.d(TAG, "Syncing by adding a point. " + x + ", " + y);
        mData.add(x, y);
        reconfigure();
        repaint();
    }

    public void sync(List<PointD> points) {
        Log.d(TAG, "Syncing by replacing the list of points, new length is "
                + points.size());
        synchronized (mData) {
            clear();
            for (PointD point : points) {
                mData.add(point.x, point.y);
            }
        }
        reconfigure();
        repaint();
    }

    public void sync(final SleepSession sleepRecord) {
        Log.d(TAG, "Attempting to sync with sleep record: " + sleepRecord);

        mData.set(com.androsz.electricsleepbeta.util.PointD
                .convertToNew(sleepRecord.getData()));

        // TODO this need to take into account timezone information.
        if (mShowTitle) 
        {
            mRenderer.setChartTitle(sleepRecord.getTitle(mContext));
        }

        // setCalibrationLevel currently reconfigures and repaints.
        // if that changes, we will need a reconfigure and repaint here too.
        setCalibrationLevelAndRedraw(sleepRecord.getCalibrationLevel());
    }

    public void clear() {
        mData.clear();
        repaint();
    }

    /**
     * Set the chart's axis format based upon current duration of the data.
     */
    private void setupChartAxisFormat() {

        mRenderer.setShowLabels(mShowLabels);
        final double duration;
        String axisFormat;
        duration = mData.getDuration();

        final int MSEC_PER_MINUTE = 1000 * 60;
        final int MSEC_PER_HOUR = MSEC_PER_MINUTE * 60;

        if (duration > (15 * MSEC_PER_MINUTE)) 
        {
            axisFormat = "h:mm";
        }
        else 
        {
            axisFormat = "h:mm:ss";
        }

        if (!axisFormat.equals(mAxisFormat)) 
        {
            mAxisFormat = axisFormat;
            try 
            {
                ((TimeChart) mChart).setDateFormat(mAxisFormat);
            } catch (ClassCastException cce) {
                Log.w(TAG,
                        "Could not set the SleepChart's axis format because the underlying chart is not a TimeChart.");
            }
        }
    }

    /**
     * Helper method that initializes charting after insertion of data.
     */
    private void setupData() {
        synchronized (mData) {

            // remove all existing series
            for (int i = 0; i < mDataset.getSeriesCount(); i++) {
                mDataset.removeSeries(i);
            }
            for (int i = 0; i < mRenderer.getSeriesRendererCount(); i++) {
                mRenderer
                        .removeSeriesRenderer(mRenderer.getSeriesRendererAt(i));
            }

            // add series to the dataset and renderer
            mData.attachToDataset(mDataset);
            mData.attachToRenderer(mRenderer);
        }

        final float textSize = MathUtils.calculatePxFromSp(mContext, 14);
        mRenderer.setChartTitleTextSize(textSize);
        mRenderer.setAxisTitleTextSize(textSize);
        mRenderer.setLabelsTextSize(textSize);

        mRenderer.setAntialiasing(true);
        mRenderer.setFitLegend(true);
        mRenderer.setLegendTextSize(textSize);
        mRenderer.setXLabels(mXLabelTicks);
        mRenderer.setYLabels(8);
        mRenderer.setYLabelsAlign(Align.RIGHT);

        setupStyle();
        // this ensures that labels are not drawn until we have data.
        mRenderer.setShowLabels(false);
    }

    /**
     * Iterate over the known attributes for this view setting our chart to the
     * desired settings.
     */
    private void setupStyle() {
        // TODO remove comment
        // After this point buildChart() should have been invoked and the
        // various renders and series
        // should have been populated.

        if (mAttrs == null) {
            Log.d(TAG, "No attributes nothing to process.");
            return;
        }

        Log.d(TAG, "Processing attributes.");

        // background color processing
        if (mSetBackgroundColor) {
            mRenderer.setBackgroundColor(mBackgroundColor);
            mRenderer.setMarginsColor(mBackgroundColor);
            mRenderer.setApplyBackgroundColor(true);
        } else {
            mRenderer.setBackgroundColor(Color.TRANSPARENT);
            mRenderer.setMarginsColor(Color.TRANSPARENT);
            mRenderer.setApplyBackgroundColor(true);
        }

        if (mSetTextColor) {
            mRenderer.setLabelsColor(mTextColor);
            mRenderer.setAxesColor(mTextColor);
        }

        // SleepChart_setScroll
        mRenderer.setInScroll(mSetInScroll);

        // SleepChart_gridAxisColor
        if (mSetGridColor) {
            mRenderer.setGridColor(mGridColor);
        } else {
            mRenderer.setGridColor(R.color.sleepchart_axis);
        }

        mData.setSeriesColors(mMovementColor, mMovementBorderColor,
                mCalibrationColor, mCalibrationBorderColor);

        // SleepChart_showGrid
        mRenderer.setShowGrid(mShowGrid);

        Resources res = mContext.getResources();
        int[] margins = mRenderer.getMargins();
        mRenderer.setShowLabels(mShowLabels);
        if (mShowLabels) {
            try {
                margins[1] += res.getDimension(R.dimen.sleep_chart_left_margin);
            } catch (android.content.res.Resources.NotFoundException e) {
                margins[1] += DEFAULT_LEFT_MARGIN; // increase left margin
            }
        }
        mRenderer.setShowLegend(mShowLegend);
        if (mShowLegend) {
            try {
                margins[2] += res
                        .getDimension(R.dimen.sleep_chart_bottom_margin);
            } catch (android.content.res.Resources.NotFoundException e) {
                margins[2] += DEFAULT_BOTTOM_MARGIN; // increase bottom margin
            }
        }
        if (mShowTitle) {
            try {
                margins[0] += res.getDimension(R.dimen.sleep_chart_top_margin);
            } catch (android.content.res.Resources.NotFoundException e) {
                margins[0] += DEFAULT_TOP_MARGIN; // increase top margin
            }
        }
        mRenderer.setMargins(margins);
    }
}
公共类睡眠图扩展GraphicalView
{
私有静态最终字符串标记=SleepChart.class.getSimpleName();
/**默认的X标签标记数*/
私有静态最终整数默认值\u X\u标签\u刻度=5;
最终语境;
//公共评级;
私有XYmultiplesseriesdataset mDataset;
私有XYMultiplesriesRenderer-mRenderer;
私有整数默认值\u底部\u边距=20;
私有整数默认值左边距=25;
私有整数默认值\u顶部\u边距=20;
背景色;
int-mTextColor;
int mCalibra
  public class SleepChart extends GraphicalView 
{
    private static final String TAG = SleepChart.class.getSimpleName();

    /** The default number of X label ticks. */
    private static final int DEFAULT_X_LABEL_TICKS = 5;

    final Context mContext;

    //public int rating;

    private XYMultipleSeriesDataset mDataset;

    private XYMultipleSeriesRenderer mRenderer;

    private int DEFAULT_BOTTOM_MARGIN = 20;
    private int DEFAULT_LEFT_MARGIN = 25;
    private int DEFAULT_TOP_MARGIN = 20;

    int mBackgroundColor;
    int mTextColor;
    int mCalibrationBorderColor;
    int mCalibrationColor;
    int mGridColor;
    int mMovementBorderColor;
    int mMovementColor;
    int mXLabelTicks;
    boolean mSetBackgroundColor;
    boolean mSetGridColor;
    boolean mSetInScroll;
    boolean mSetTextColor;
    boolean mShowGrid;
    boolean mShowLabels;
    boolean mShowLegend;
    boolean mShowTitle = true;

    private String mAxisFormat;

    public final SleepChartData mData;

    int mDefStyle;

    AttributeSet mAttrs;


    public SleepChart(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SleepChart(Context context , AbstractChart chart)
    {
        super(context, chart);

        mContext = context;

        //mAttrs = attrs;
        //mDefStyle = defStyle;
        mData = new SleepChartData(mContext);

        setupData();
    }

    public SleepChart(final Context context, final AttributeSet attrs,
            int defStyle)
    {
        super(context, attrs);

        mContext = context;
        mAttrs = attrs;
        mDefStyle = defStyle;
        mData = new SleepChartData(mContext);

        // Now begin processing attributes
        TypedArray array = mContext.obtainStyledAttributes(mAttrs,
                R.styleable.SleepChart, mDefStyle, 0);

        if (array.hasValue(R.styleable.SleepChart_android_background)) {
            mSetBackgroundColor = true;
            mBackgroundColor = array.getColor(
                    R.styleable.SleepChart_android_background,
                    R.color.background_dark);
        }

        if (array.hasValue(R.styleable.SleepChart_android_textColor)) {
            mSetTextColor = true;
            mTextColor = array
                    .getColor(R.styleable.SleepChart_android_textColor,
                            R.color.text_dark);
        }

        if (array.getBoolean(R.styleable.SleepChart_setScroll, false)) {
            mSetInScroll = true;
        }

        if (array.hasValue(R.styleable.SleepChart_gridAxisColor)) {
            mSetGridColor = true;
            mGridColor = array.getColor(R.styleable.SleepChart_gridAxisColor,
                    R.color.sleepchart_axis);
        }

        mXLabelTicks = array.getInteger(R.styleable.SleepChart_xLabelTicks,
                DEFAULT_X_LABEL_TICKS);

        mMovementColor = array.getColor(R.styleable.SleepChart_movementColor,
                R.color.sleepchart_movement_light);

        mMovementBorderColor = array.getColor(
                R.styleable.SleepChart_movementBorderColor,
                R.color.sleepchart_movement_border_light);

        mCalibrationColor = array.getColor(
                R.styleable.SleepChart_calibrationColor,
                R.color.sleepchart_calibration_light);

        mCalibrationBorderColor = array.getColor(
                R.styleable.SleepChart_calibrationBorderColor,
                R.color.sleepchart_calibration_border_light);

        mShowGrid = array.getBoolean(R.styleable.SleepChart_showGrid, true);

        mShowLabels = array.getBoolean(R.styleable.SleepChart_showLabels, true);
        mShowLegend = array.getBoolean(R.styleable.SleepChart_showLegend, true);
        mShowTitle = array.getBoolean(R.styleable.SleepChart_showTitle, true);

        setupData();
    }

//  @Override
    protected AbstractChart buildChart() 
    {
        Log.d(TAG, "Attempting to build chart.");

        if (mChart != null) {
            Log.w(TAG, "Attempt to build chart when chart already exists.");
            return mChart;
        }

        mDataset = new XYMultipleSeriesDataset();
        mRenderer = new XYMultipleSeriesRenderer();
        // Set initial framing for renderer.
        mRenderer.setYAxisMin(0);
        // Referencing SettingsActivity.MAX_ALARM_SENSITIVITY causes errors in ADT.
        if (isInEditMode()) {
            mRenderer.setYAxisMax(1.0f);
        } else {
            mRenderer.setYAxisMax(SettingsActivity.MAX_ALARM_SENSITIVITY);
        }
        mRenderer.setXAxisMin(System.currentTimeMillis());
        mRenderer.setXAxisMax(System.currentTimeMillis());
        mRenderer.setPanEnabled(false, false);
        mRenderer.setZoomEnabled(false, false);

        TimeChart timeChart = new TimeChart(mDataset, mRenderer);
        timeChart.setDateFormat("h:mm:ss");
        mChart = timeChart;

        return mChart;
    }

    /**
     * Return the calibration level if one is available; otherwise return
     * INVALID_CALIBRATION.
     * 
     * Callers of this method could call hasCalibrationLevel first to determine
     * if information surrounding calibration is available prior to invoking
     * this method.
     */
    public float getCalibrationLevel() {
        return mData.getCalibrationLevel();
    }

    public boolean hasTwoOrMorePoints() {
        return mData.hasTwoOrMorePoints();
    }

    public void reconfigure() {
        if (hasTwoOrMorePoints()) {
            synchronized (mData) {
                final double firstX = mData.getLeftMostTime();
                final double lastX = mData.getRightMostTime();

                mData.setupCalibrationSpan(firstX, lastX);

                mRenderer.setXAxisMin(firstX);
                mRenderer.setXAxisMax(lastX);
            }

            setupChartAxisFormat();
        } else {
            Log.w(TAG,
                    "Asked to reconfigure but it did not make sense to display.");
        }
    }

    public void setCalibrationLevelAndRedraw(final float calibrationLevel) {
        mData.setCalibrationLevel(calibrationLevel);
        reconfigure();
        repaint();
    }

    public void setScroll(boolean scroll) {
        mSetInScroll = scroll;
    }

    public void sync(final Cursor cursor) throws StreamCorruptedException,
            IllegalArgumentException, IOException, ClassNotFoundException {
        Log.d(TAG, "Attempting to sync with cursor: " + cursor);
        this.sync(new SleepSession(cursor));
    }

    public void sync(final Double x, final Double y) {
        Log.d(TAG, "Syncing by adding a point. " + x + ", " + y);
        mData.add(x, y);
        reconfigure();
        repaint();
    }

    public void sync(List<PointD> points) {
        Log.d(TAG, "Syncing by replacing the list of points, new length is "
                + points.size());
        synchronized (mData) {
            clear();
            for (PointD point : points) {
                mData.add(point.x, point.y);
            }
        }
        reconfigure();
        repaint();
    }

    public void sync(final SleepSession sleepRecord) {
        Log.d(TAG, "Attempting to sync with sleep record: " + sleepRecord);

        mData.set(com.androsz.electricsleepbeta.util.PointD
                .convertToNew(sleepRecord.getData()));

        // TODO this need to take into account timezone information.
        if (mShowTitle) 
        {
            mRenderer.setChartTitle(sleepRecord.getTitle(mContext));
        }

        // setCalibrationLevel currently reconfigures and repaints.
        // if that changes, we will need a reconfigure and repaint here too.
        setCalibrationLevelAndRedraw(sleepRecord.getCalibrationLevel());
    }

    public void clear() {
        mData.clear();
        repaint();
    }

    /**
     * Set the chart's axis format based upon current duration of the data.
     */
    private void setupChartAxisFormat() {

        mRenderer.setShowLabels(mShowLabels);
        final double duration;
        String axisFormat;
        duration = mData.getDuration();

        final int MSEC_PER_MINUTE = 1000 * 60;
        final int MSEC_PER_HOUR = MSEC_PER_MINUTE * 60;

        if (duration > (15 * MSEC_PER_MINUTE)) 
        {
            axisFormat = "h:mm";
        }
        else 
        {
            axisFormat = "h:mm:ss";
        }

        if (!axisFormat.equals(mAxisFormat)) 
        {
            mAxisFormat = axisFormat;
            try 
            {
                ((TimeChart) mChart).setDateFormat(mAxisFormat);
            } catch (ClassCastException cce) {
                Log.w(TAG,
                        "Could not set the SleepChart's axis format because the underlying chart is not a TimeChart.");
            }
        }
    }

    /**
     * Helper method that initializes charting after insertion of data.
     */
    private void setupData() {
        synchronized (mData) {

            // remove all existing series
            for (int i = 0; i < mDataset.getSeriesCount(); i++) {
                mDataset.removeSeries(i);
            }
            for (int i = 0; i < mRenderer.getSeriesRendererCount(); i++) {
                mRenderer
                        .removeSeriesRenderer(mRenderer.getSeriesRendererAt(i));
            }

            // add series to the dataset and renderer
            mData.attachToDataset(mDataset);
            mData.attachToRenderer(mRenderer);
        }

        final float textSize = MathUtils.calculatePxFromSp(mContext, 14);
        mRenderer.setChartTitleTextSize(textSize);
        mRenderer.setAxisTitleTextSize(textSize);
        mRenderer.setLabelsTextSize(textSize);

        mRenderer.setAntialiasing(true);
        mRenderer.setFitLegend(true);
        mRenderer.setLegendTextSize(textSize);
        mRenderer.setXLabels(mXLabelTicks);
        mRenderer.setYLabels(8);
        mRenderer.setYLabelsAlign(Align.RIGHT);

        setupStyle();
        // this ensures that labels are not drawn until we have data.
        mRenderer.setShowLabels(false);
    }

    /**
     * Iterate over the known attributes for this view setting our chart to the
     * desired settings.
     */
    private void setupStyle() {
        // TODO remove comment
        // After this point buildChart() should have been invoked and the
        // various renders and series
        // should have been populated.

        if (mAttrs == null) {
            Log.d(TAG, "No attributes nothing to process.");
            return;
        }

        Log.d(TAG, "Processing attributes.");

        // background color processing
        if (mSetBackgroundColor) {
            mRenderer.setBackgroundColor(mBackgroundColor);
            mRenderer.setMarginsColor(mBackgroundColor);
            mRenderer.setApplyBackgroundColor(true);
        } else {
            mRenderer.setBackgroundColor(Color.TRANSPARENT);
            mRenderer.setMarginsColor(Color.TRANSPARENT);
            mRenderer.setApplyBackgroundColor(true);
        }

        if (mSetTextColor) {
            mRenderer.setLabelsColor(mTextColor);
            mRenderer.setAxesColor(mTextColor);
        }

        // SleepChart_setScroll
        mRenderer.setInScroll(mSetInScroll);

        // SleepChart_gridAxisColor
        if (mSetGridColor) {
            mRenderer.setGridColor(mGridColor);
        } else {
            mRenderer.setGridColor(R.color.sleepchart_axis);
        }

        mData.setSeriesColors(mMovementColor, mMovementBorderColor,
                mCalibrationColor, mCalibrationBorderColor);

        // SleepChart_showGrid
        mRenderer.setShowGrid(mShowGrid);

        Resources res = mContext.getResources();
        int[] margins = mRenderer.getMargins();
        mRenderer.setShowLabels(mShowLabels);
        if (mShowLabels) {
            try {
                margins[1] += res.getDimension(R.dimen.sleep_chart_left_margin);
            } catch (android.content.res.Resources.NotFoundException e) {
                margins[1] += DEFAULT_LEFT_MARGIN; // increase left margin
            }
        }
        mRenderer.setShowLegend(mShowLegend);
        if (mShowLegend) {
            try {
                margins[2] += res
                        .getDimension(R.dimen.sleep_chart_bottom_margin);
            } catch (android.content.res.Resources.NotFoundException e) {
                margins[2] += DEFAULT_BOTTOM_MARGIN; // increase bottom margin
            }
        }
        if (mShowTitle) {
            try {
                margins[0] += res.getDimension(R.dimen.sleep_chart_top_margin);
            } catch (android.content.res.Resources.NotFoundException e) {
                margins[0] += DEFAULT_TOP_MARGIN; // increase top margin
            }
        }
        mRenderer.setMargins(margins);
    }
}