Android - Sugar ORM 保存崩溃

Android - Sugar ORM Save Crash

我正在尝试将 Sugar ORM (v 1.3) 集成到我的 Android 应用程序中,但在尝试保存新创建的实体时我总是遇到崩溃 (NullPointerException)。

这是我的崩溃...

01-21 06:02:36.012    2856-2856/com.spuddmobile.kel E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.spuddmobile.kel, PID: 2856
    java.lang.NullPointerException
            at com.orm.SugarRecord.save(SugarRecord.java:109)
            at com.orm.SugarRecord.save(SugarRecord.java:45)
            at com.spuddmobile.kel.Fragments.NewAppFragment._SaveForm(NewAppFragment.java:231)
            at com.spuddmobile.kel.Fragments.NewAppFragment.onMenuItemSelection(NewAppFragment.java:175)
            at com.spuddmobile.kel.Activities.MainActivity.onOptionsItemSelected(MainActivity.java:89)
            at android.app.Activity.onMenuItemSelected(Activity.java:2600)
            at com.android.internal.policy.impl.PhoneWindow.onMenuItemSelected(PhoneWindow.java:1012)
            at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:735)
            at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
            at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:874)
            at com.android.internal.view.menu.ActionMenuView.invokeItem(ActionMenuView.java:546)
            at com.android.internal.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:115)
            at android.view.View.performClick(View.java:4438)
            at android.view.View$PerformClick.run(View.java:18422)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)

这是我的AppManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.spuddmobile.kel" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:name="com.orm.SugarApp"
        android:theme="@style/AppTheme" >

        <meta-data android:name="DATABASE" android:value="kel.db" />
        <meta-data android:name="VERSION" android:value="1" />
        <meta-data android:name="QUERY_LOG" android:value="true" />
        <meta-data android:name="DOMAIN_PACKAGE_NAME" android:value="com.spuddmobile.kel.Model" />

        <activity
            android:name=".Activities.MainActivity"
            android:label="@string/app_name"
            android:windowSoftInputMode="stateHidden|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="android.support.UI_OPTIONS" android:value="splitActionBarWhenNarrow" />
        </activity>
    </application>

</manifest>

如您所见,我确实根据文档将 android:name 设置为 com.orm.SugarApp

这是我的 entity/domain class...

public class Appraisal extends SugarRecord<Appraisal>
{
    Double rent;
    Integer area;
    Integer currentPeriod;
    Integer reviewFrequency;
    Integer rentFreePeriod;
    Integer interimRentPeriod;
    Double interimRentPrice;
    Integer secondInterimRentPeriod;
    Double secondInterimRentPrice;
    Double incentives;
    Integer breakPeriod;
    Double breakPenalty;
    Double breakIncentiveRent;
    Integer breakIncentiveRentPeriod;
    Double breakRisk;
    String name;
    Date createdDate;
    Date updatedDate;

    public Appraisal ()
    {

    }

    public Appraisal (Double rent,
                      Integer area,
                      Integer currentPeriod,
                      Integer reviewFrequency,
                      Integer rentFreePeriod,
                      Integer interimRentPeriod,
                      Double interimRentPrice,
                      Integer secondInterimRentPeriod,
                      Double secondInterimRentPrice,
                      Double incentives,
                      Integer breakPeriod,
                      Double breakPenalty,
                      Double breakIncentiveRent,
                      Integer breakIncentiveRentPeriod,
                      Double breakRisk,
                      String name,
                      Date createdDate,
                      Date updatedDate)
    {
        this.rent = rent;
        this.area = area;
        this.currentPeriod = currentPeriod;
        this.reviewFrequency = reviewFrequency;
        this.rentFreePeriod = rentFreePeriod;
        this.interimRentPeriod = interimRentPeriod;
        this.interimRentPrice = interimRentPrice;
        this.secondInterimRentPeriod = secondInterimRentPeriod;
        this.secondInterimRentPrice = secondInterimRentPrice;
        this.incentives = incentives;
        this.breakPeriod = breakPeriod;
        this.breakPenalty = breakPenalty;
        this.breakIncentiveRent = breakIncentiveRent;
        this.breakIncentiveRentPeriod = breakIncentiveRentPeriod;
        this.breakRisk = breakRisk;
        this.name = name;
        this.createdDate = createdDate;
        this.updatedDate = updatedDate;
    }
}

请注意,我的实体实际上扩展了 SugarRecord,并且我确实提供了所需的空构造函数和参数化构造函数。我没有用上下文覆盖 super init 方法,因为根据 Sugar ORM v1.3 中不再需要的文档。

最后,崩溃的代码...

// create new app
Appraisal nApp = new Appraisal();
nApp.save();

存档崩溃了。现在,我已经通过 Android 设备监视器检查以确保正确创建了数据库,并且它确实存在并具有评估 table。但是,当我查询 table 时它是空的,这是有道理的,因为 Sugar 从未完成 save() 函数。

有人知道我这里做错了吗?为了确保我提供了所有相关信息,我的 Gradle 构建脚本如下。

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.0.0'
    }
}

apply plugin: 'android'

android {
    compileSdkVersion 13
    buildToolsVersion '19.1.0'
    defaultConfig {
        applicationId 'com.spuddmobile.kel'
        minSdkVersion 13
        targetSdkVersion 17
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
    productFlavors {}
}

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.noveogroup.android:android-logger:1.3.4'
    compile 'com.github.satyan:sugar:1.3'
}

您的实体有一个默认的无参数构造函数,您不会在其中初始化任何字段...因此您的字段的每个值都是 null

因为你有 NullPointerException,如果我是你,我会尝试用默认值初始化每个字段。例如:

public Appraisal ()
{
    this.rent = 0.0;
    this.area = 0;
    ...
}

Sugar ORM 将确认类型为 java.sql.Timestamp 的空对象。

这可能会破坏您代码的其他部分(例如,等号无法比较 java.sql.Timestamp 和 java.util.Date)。