0

Я использую AndroidAnnotations и SQLite с ORMLite и пытаюсь запустить базу данных. Несколько дней назад я смог создать таблицу и сделать тестовую вставку объекта Contact. Тем не менее, я сделал некоторые изменения, а затем прекратил работать - к сожалению, я не смог отменить свои изменения, и теперь я застрял и больше не могу работать.Получение NullPointerException с AndroidAnnotations и ORMLite

Всякий раз, когда я запустить приложение я получаю эту ошибку:

02-12 23:09:39.931 11766-11766/net.gazeapp E/AndroidRuntime: FATAL EXCEPTION: main 
Process: net.gazeapp, PID: 11766 
java.lang.RuntimeException: Unable to start activity ComponentInfo{net.gazeapp/net.gazeapp.MainActivity_}: java.lang.NullPointerException: Attempt to invoke virtual method 'int net.gazeapp.data.ContactDao.create(java.lang.Object)' on a null object reference 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int net.gazeapp.data.ContactDao.create(java.lang.Object)' on a null object reference 
at net.gazeapp.service.ContactService.addContact(ContactService.java:55) 
at net.gazeapp.MainActivity.testNewORM(MainActivity.java:171) 
at net.gazeapp.MainActivity.createView(MainActivity.java:148) 
at net.gazeapp.MainActivity_.onViewChanged(MainActivity_.java:111) 
at org.androidannotations.api.view.OnViewChangedNotifier.notifyViewChanged(OnViewChangedNotifier.java:41) 
at net.gazeapp.MainActivity_.setContentView(MainActivity_.java:57) 
at net.gazeapp.MainActivity_.onCreate(MainActivity_.java:45) 
at android.app.Activity.performCreate(Activity.java:6251) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)  
at android.app.ActivityThread.-wrap11(ActivityThread.java)  
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)  
at android.os.Handler.dispatchMessage(Handler.java:102)  
at android.os.Looper.loop(Looper.java:148)  
at android.app.ActivityThread.main(ActivityThread.java:5417)  
at java.lang.reflect.Method.invoke(Native Method)  
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)  
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)  

Так вот мой MainActivity, в котором я делаю ORM-тестирование (в методе testNewORM()):

@EActivity(R.layout.activity_main_viewpagertab) 
@OptionsMenu(R.menu.menu_main) 
public class MainActivity extends BaseActivity implements ObservableScrollViewCallbacks { 

    private final String TAG = getClass().getSimpleName(); 

    private int mBaseTranslationY; 
    private NavigationAdapter mPagerAdapter; 
    private Contact mContact; 

    private static String[] tabTitles = null; 

    @App 
    GazeApplication application; 

    @ViewById(R.id.header) 
    View mHeaderView; 

    @ViewById(R.id.toolbar) 
    View mToolbarView; 

    @ViewById(R.id.pager) 
    ViewPager mPager; 

    @ViewById(R.id.fab) 
    FloatingActionButton fab; 

    @ViewById(R.id.adview) 
    MoPubView mAdView; 

    @Bean 
    ContactService contactService; 

    @AfterViews 
    void createView() { 
     setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); 

     Tools.readJsonFile(this, "fetishes.json"); 

     // TAB TITLES: RECENT, ALL, MY MEDIA 
     tabTitles = new String[]{getString(R.string.recent), getString(R.string.all), getString(R.string.my_media)}; 

     ViewCompat.setElevation(mHeaderView, getResources().getDimension(R.dimen.toolbar_elevation)); 

     mPagerAdapter = new NavigationAdapter(getSupportFragmentManager()); 
     mPager.setAdapter(mPagerAdapter); 

     SlidingTabLayout slidingTabLayout = (SlidingTabLayout) findViewById(R.id.sliding_tabs); 
     slidingTabLayout.setCustomTabView(R.layout.tab_indicator, android.R.id.text1); 
     slidingTabLayout.setSelectedIndicatorColors(getResources().getColor(R.color.colorAccent)); 
     slidingTabLayout.setDistributeEvenly(true); 
     slidingTabLayout.setViewPager(mPager); 

     // When the page is selected, other fragments' scrollY should be adjusted 
     // according to the toolbar status(shown/hidden) 
     slidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
      @Override 
      public void onPageScrolled(int i, float v, int i2) { 
      } 

      @Override 
      public void onPageSelected(int i) { 
       propagateToolbarState(toolbarIsShown()); 
      } 

      @Override 
      public void onPageScrollStateChanged(int i) { 
      } 
     }); 

     propagateToolbarState(toolbarIsShown()); 

     displayAdBanner(); 

     // TESTING ORMAPPER 
     // TESTING ORMAPPER 
     testNewORM(); 
    } 

    void testNewORM() { 
     java.util.Date date = new java.util.Date(); 
     Timestamp timeNow = new Timestamp(date.getTime()); 

     Timestamp birthdateTimestamp = new Timestamp(date.getTime()); 
     Date birthdate = new Date(); 

     try { 
      DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); 
      birthdate = dateFormat.parse("04/07/1980"); 
      long time = birthdate.getTime(); 
      birthdateTimestamp = new Timestamp(time); 
     } catch (ParseException e) { 
      e.printStackTrace(); 
     } 

     Contact contact = new Contact("Dominik Erbsland"); 
     contact.setBirthdate(birthdate); 

     try { 
      mContact = contactService.addContact(contact); 
     } catch (ItemNotFoundException | SQLException e) { 
      Log.e(TAG, e.getLocalizedMessage()); 
      e.printStackTrace(); 
     } 
    } 

... 
} 

И здесь другие используемые классы:

@EBean(scope = EBean.Scope.Singleton) 
public class ContactService { 

    private static final String TAG = ContactService.class.getSimpleName(); 

    @RootContext 
    Context ctx; 

    @OrmLiteDao(helper = DatabaseHelper.class) 
    ContactDao mContactDao; 

    public Contact getContact(int contactId) throws ItemNotFoundException, SQLException { 
     Contact contact = mContactDao.queryForId(contactId); 
     if (contact == null) { 
      Log.e(TAG, "Contact not found in database"); 
      throw new ItemNotFoundException(); 
     } 

     return contact; 
    } 

    public List<Contact> getContacts() throws ItemNotFoundException, SQLException { 
     List<Contact> contact = mContactDao.queryForAll(); 
     if (contact == null) { 
      Log.e(TAG, "Contacts not found in database"); 
      throw new ItemNotFoundException(); 
     } 

     return contact; 
    } 

    public Contact addContact(Contact contact) throws SQLException { 
     int rowsAffected = 0; 
     try { 
      rowsAffected = mContactDao.create(contact); 
     } catch (SQLException e) { 
      Log.e(TAG, e.getLocalizedMessage()); 
      e.printStackTrace(); 
     } 

     Log.d(TAG, "New Contact ID: " + contact.getId()); 

     return contact; 
    } 

    public void testOutput() { 
     Log.d(TAG, "THIS IS A TEST OUTPUT"); 
    } 

} 

здесь моя база данных помощник:

public class DatabaseHelper extends OrmLiteSqliteOpenHelper { 

    private static final String DATABASE_NAME = "Gaze.db"; 
    private static final int DATABASE_VERSION = 1; 
    private final Context context; 

    // the DAO object we use to access the Person table 
    private Dao<Contact, Integer> contactDao = null; 
    private Dao<MyPreferences, Integer> preferencesDao = null; 
    private Dao<SecurityQuestion, Integer> securityQuestionDao = null; 

    public DatabaseHelper(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     this.context = context; 
    } 

    /** 
    * This is called when the database is first created. Usually you should call createTable statements here to create 
    * the tables that will store your data. 
    */ 
    @Override 
    public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) { 
     try { 
      Log.i(DatabaseHelper.class.getName(), "onCreate"); 

      TableUtils.createTable(connectionSource, Contact.class); 
     } catch (SQLException e) { 
      Log.e(DatabaseHelper.class.getName(), "Can't create database", e); 
      throw new RuntimeException(e); 
     } 
    } 

    /** 
    * This is called when your application is upgraded and it has a higher version number. This allows you to adjust 
    * the various data to match the new version number. 
    */ 
    @Override 
    public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) { 
     try { 
      Log.i(DatabaseHelper.class.getName(), "onUpgrade"); 
      TableUtils.dropTable(connectionSource, Contact.class, true); 
      // after we drop the old databases, we create the new ones 
      onCreate(db, connectionSource); 
     } catch (SQLException e) { 
      Log.e(DatabaseHelper.class.getName(), "Can't drop databases", e); 
      throw new RuntimeException(e); 
     } 
    } 

    /** 
    * Returns the Database Access Object (DAO) for our Person class. It will create it or just give the cached 
    * value. 
    */ 
    public Dao<Contact, Integer> getContactDao() throws SQLException { 
     if (contactDao == null) { 
      contactDao = getDao(Contact.class); 
     } 
     return contactDao; 
    } 

    public Dao<MyPreferences, Integer> getPreferencesDao() throws SQLException { 
     if (preferencesDao == null) { 
      preferencesDao = getDao(MyPreferences.class); 
     } 
     return preferencesDao; 
    } 

    public Dao<SecurityQuestion, Integer> getSecurityQuestionDao() throws SQLException { 
     if (securityQuestionDao == null) { 
      securityQuestionDao = getDao(SecurityQuestion.class); 
     } 
     return securityQuestionDao; 
    } 

    /** 
    * Close the database connections and clear any cached DAOs. 
    */ 
    @Override 
    public void close() { 
     super.close(); 
     contactDao = null; 
     preferencesDao = null; 
     securityQuestionDao = null; 
    } 
}                

и класс данных:

@DatabaseTable(tableName = "Contact", daoClass = ContactDao.class) 
public class Contact implements Serializable { 

    @DatabaseField(generatedId = true, columnName = PersistentObject.ID) 
    int id; 

    @DatabaseField(index = true) 
    String contactName; 

    @DatabaseField 
    String mainPic; 

    @DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss.S") 
    Date birthdate; 

    @DatabaseField 
    boolean knowPersonally; 

    @DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss.S") 
    Timestamp created; 

    @DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss.S") 
    Timestamp lastMod; 

    public Contact() { 
     // needed by ormlite 
    } 

... 
} 

и ContactDAO:

public class ContactDao extends BaseDaoImpl<Contact, Integer> { 

    public ContactDao(Class<Contact> dataClass) throws SQLException { 
     super(dataClass); 
    } 

    public ContactDao(ConnectionSource connectionSource, Class<Contact> dataClass) throws SQLException { 
     super(connectionSource, dataClass); 
    } 

    public ContactDao(ConnectionSource connectionSource, DatabaseTableConfig<Contact> tableConfig) throws SQLException { 
     super(connectionSource, tableConfig); 
    } 

    public List<Contact> getContacts() throws SQLException { 
     return queryForAll(); 
    } 

} 

Таким образом, в классе ContactService в "mContactDao.create (контакт);" он разбился с Исключением. Это та часть, которую я не понимаю, потому что ContactService аннотируется с помощью @EBean и к ней обращаются в MainActivity с помощью «@Bean ContactService contactService;» и не должно быть там ...

Спасибо за любую помощь или подсказки заранее.

+0

Можете ли вы поделиться проектом или сокращенным проектом? – WonderCsabo

+0

Да, конечно. Я сократил проект до базовых классов. Вот ссылка для скачивания: http://www.cheat-database.com/Gaze-reduced.zip - Спасибо большое! –

+0

'mContactDao' никогда не инициализируется. – Flovdis

ответ

2

Проблема заключается в следующем:

код пытается получить доступ к mContactDao поле, но это действительно null, Altough следует впрыскивается AndroidAnnotations. Но поле не может быть введено, потому что создание dao завершается с исключением. Это зарегистрировано AndroidAnnotations, вы можете проверить его в LogCat.

Причина проблемы заключается в классе Contact. Вы используете поля List<Something>, но ORMLite не знает, как сохранить объект java.util.List. Вы можете использовать пользовательскую стойкую бактерию, или вы можете использовать внешние поля:

Contact.java:

@ForeignCollectionField 
private ForeignCollection<Address> adresses; 

Update:

Применение ForestCollectionField изменения и отладки снова показали еще одну проблему. Точка DataType.DATE_STRING не может использоваться с классом java.sql.Timestamp. Но вместо этого вы можете использовать DataType.TIME_STAMP:

@DatabaseField(dataType = DataType.TIME_STAMP, format = "yyyy-MM-dd HH:mm:ss.S") 
Timestamp created; 

@DatabaseField(dataType = DataType.TIME_STAMP, format = "yyyy-MM-dd HH:mm:ss.S") 
Timestamp lastMod; 
+0

теперь я изменил все поля Contact.java к ForeignCollectionField, но я все еще получаю ту же ошибку: '@ForeignCollectionField ForeignCollection

адреса ; ' Ошибка: ' java.lang.RuntimeException: не удалось запустить активность ComponentInfo {net.gazeapp/net.gazeapp.MainActivity_}: java.lang.NullPointerException: попытка вызвать виртуальный метод 'int net.gazeapp .data.ContactDao.create (java.lang.Object) 'в ссылке на нулевой объект в android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2416) ' –

+0

О, спасибо, подсказка w поскольку «dataType = DataType.TIME_STAMP» на самом деле был ключом к избавлению от ошибки. Также я забыл добавить «foreign = true» к некоторым объектам внешнего ключа: «@DatabaseField (foreign = true) Персональный персонаж; Теперь это работает до сих пор! Большое спасибо! –

+0

Отметьте ответ как принятый, затем. ;) – WonderCsabo