打开作业提供的素材项目,提示no such table: dish_tb 找不到dish_tb表

打开作业提供的素材项目,提示no such table: dish_tb 找不到dish_tb表

http://img1.sycdn.imooc.com//climg/5dcba2be096e277d00000000.jpg上图中提示找不到dish_tb表。


既然提示找不到,就把这个数据库拷贝到电脑上来,用数据库软件打开后 dish_tb表是存在的啊,很是令人费解。

http://img1.sycdn.imooc.com//climg/5dcba307092b9e7600000000.jpg


然后通过ADB打开数据库查看,跟运行时崩溃提示的一样,数据库中没有 dish_tb表,然后新建了一个test表如下图:

http://img1.sycdn.imooc.com//climg/5dcba3a00961899307030383.jpg

新建test表后再拷贝到电脑上打开,之前的表全消失了,剩下的是在adb里查看到的表,如下图

http://img1.sycdn.imooc.com//climg/5dcba3b909a0f91c05000379.jpg


我想知道这是啥问题呢??? 实在是找不出解决办法了。

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

2回答
提问者 喝白酒的兔子 2019-11-13 17:26:27

通过几个小时的折腾终于找出了真正原因:

SQLiteLog: (1) no such table: dish_tb   运行项目提示找不到表的原因分析

 

这个项目运行逻辑如下:

1、项目的原始数据库在menudemo\src\main\assets目录下。

2、当执行MainActivity类的onCreate方法时会调用 generateDatabase() 方法把assets目录下的menu.db数据库拷贝到APP的文件目录下,拷贝过去的文件名为 imooc_menu.db。

3、当数据库拷贝到APP文件目录下后,开始调用MenuDao类的静态方法getInstance()获取数据库实例,注意这是一个单例模式,同时MenuProvider内容提供器类也是通过getInstance()方法获取数据库实例来对外提供数据的。

4、在MainActivity类的onCreate方法中获取到数据库实例后就查询dish_tb表中的数据进行打印并显示到TextView中。

 

正常来说,这个逻辑并没有什么问题,因为待拷贝的menu.db数据库中确实存在dish_tb表,但是查询的时候却出现了找不到dish_tb表的问题,经过反复折腾最终找出来问题所在。

 

找不到到dish_tb表的原因就是MenuProvider内容提供器要先于MainActivity类初始化,这么一来,拷贝数据库的方法是在MainActivity类中的,这个时候拷贝数据库的方法generateDatabase() 是还没有执行的,所以这个时候APP的文件目录下是没有imooc_menu.db数据库的,而这个时候MenuProvider内容提供器类的onCreate方法会调用MenuDao.getInstance()这个方法去获取数据库实例,当创建数据库对象的时候如果没有imooc_menu.db这个文件存在的话,就直接创建了一个新数据库,然后就把这个新数据库对象返回给了内容提供器。当内容提供器初始化完成了后轮到MainActivity类进行初始化,MainActivity类拷贝menu.db数据库到APP目录下命名为imooc_menu.db(这个时候是覆盖了之前创建的新数据库),接着调用MenuDao.getInstance()获取数据库对象,因为是单例模式,获取到的对象还是原先的新数据库对象(这是重点),接着进行查询操作,这样当然是无法在新数据库中找到dish_tb表的了,所以APP崩溃了。

 

解决方法1:删除掉文件路面下的imooc_menu.db-shm 和 imooc_menu.db-wal文件,因为不删除这两个文件的话再次启动还是获取到那个没有包含dish_tb表的数据库实例,关于这两个文件的作用百度即可明白。删除这两个文件后再次运行,这次不会崩溃了,因为这次获取到的数据库实例是上一次崩溃的时候复制过去的数据库实例,而这个数据库是包含了dish_tb表的。

解决方法2:让拷贝数据库的方法在内容提供器调用MenuDao.getInstance()方法获取实例之前执行就解决了崩溃的问题。

下图是要删除的两个文件:

http://img1.sycdn.imooc.com//climg/5dcbcc0609d6931e05980321.jpg


关于内容提供器和MainActivity谁先初始化,看下图就明白了:

http://img1.sycdn.imooc.com//climg/5dcbcc3c09eba6f510720879.jpg

  • 感谢同学的分享,帮到更多的小伙伴
    2019-11-13 18:17:23
  • 提问者 喝白酒的兔子 #2
    补充:在一些API版本比较低的机型中并不会出问题,如api22,即使获取的是内容提供器获取数据库对象时创建的那个全新数据库的对象,也可以访问后来复制过去的那个数据库的表。
    2019-11-19 17:25:25
irista23 2019-11-13 15:53:12

可以参考这里老师和同学们的解决方法

https://class.imooc.com/course/qadetail/124419

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师