如何用资产文件夹中的数据库填充ListView? [英] How to populate ListView with db in asset folder?

查看:86
本文介绍了如何用资产文件夹中的数据库填充ListView?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我想制作一个应用程序,列出我存储在我创建的现有SQLite数据库中的食物.我的foodDB.db文件位于/assets/databases文件夹中.

so I want to make an app that lists foods that I have stored in an already existing SQLite database I created. I have my foodDB.db file in the /assets/databases folder.

我知道我必须使用DatabaseHelper类.我已经做了相当多的研究,看过很多stackoverflow帖子和youtube教程,但是都没有满足我从资产文件夹中现有数据库填充ListView的要求.我觉得它们很混乱而且不清楚.

I know I must use a DatabaseHelper class. I have done my fair share of research, I have looked at plenty of stackoverflow posts and youtube tutorials but none satisfy my critera of populating a ListView from an existing database in the asset folder. I find them very confusing and not clear.

请问有人可以清楚地向我解释我该怎么做吗?我真的很努力,希望能得到一些指导.

Could someone please clearly explain to me how I would go about this? I am really struggling and would appreciate some guidance.

我的数据库称为foodDatabase.db.
我的数据库包含1个名为dataset的表.
dataset包含以下列:id, name, description, protein, fat, carbohydrates, energy, starch, sugar, cholesterol.

My database is called foodDatabase.db.
My database contains 1 table called dataset.
The table dataset contains the colums: id, name, description, protein, fat, carbohydrates, energy, starch, sugar, cholesterol.

推荐答案

首先要注意的几点.

  • 1-您已经说过文件是 FoodDB.db ,但是随后又说该数据库名为 foodDatabase.db .数据库名称是文件名.这样,以下示例将 FoodDB.db 用作资产中的文件(从资产中复制时,您可以重命名该文件,但在此答案中我没有这样做.)

  • 1 - you have said that the file is FoodDB.db but then said that the database is called foodDatabase.db. The database name is the file name. As such the following example uses FoodDB.db as the file that is in the assets (you could rename the file when copying from the assets but I've not done that in this answer.)

2-您不需要数据库助手,并且该示例不使用它.

2 - You do not need a Database Helper and the example doesn't use one.

这是两个部分:-

  • 1)访问数据库以提取ListView的数据.在以下示例中,此操作从资产复制到标准数据库位置( /data/data/the_package/databases/the_database_name ).

  • 1) Accessing the database to extract the data for the ListView. In the following example this is copied from the assets to the standard database location (/data/data/the_package/databases/the_database_name).

  • 已经做出假设,一旦从资产中复制了数据库,随后将使用该数据库(即在应用程序的生命周期中将其复制一次).

2)在ListView中显示提取的数据(作为游标获得).

2) Displaying the extracted data (obtained as a Cursor) in a ListView.

要执行2,您将需要在布局中包含ListView,因为已使用以下布局. activity_main.xml :-

To do 2 you will need the layout to include a ListView, as such the following layout has been used. activity_main.xml :-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="fooddb.so49328656populatelistview.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        />
    <ListView
        android:id="@+id/foodlist"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>
</LinearLayout>

  • 注意tools:context="fooddb.so49328656populatelistview.MainActivity"必须反映您的包裹
    • Note tools:context="fooddb.so49328656populatelistview.MainActivity" would have to reflect YOUR package
    • 数据库助手-未按警告使用

      调用活动 MainActivity.java (请参见注释):-

      The invoking activity MainActivity.java (see notes) :-

      public class MainActivity extends AppCompatActivity {
      
          static final String DBNAME = "FoodDB.db";
          static final String DBASSETPATH = "databases/" + DBNAME;
          static final String FOODTABLE = "dataset";
          static final String FOODCOLUMN = "Food";
          static final String IDCOLUMN = "ID";
      
          ListView mFoodList;
          SQLiteDatabase mDB;
          SimpleCursorAdapter mSCA;
          Cursor mCsr;
      
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              mFoodList = (ListView) this.findViewById(R.id.foodlist);
              mDB = openFoodDB();
              if (mDB != null) {
                  mCsr = mDB.query(FOODTABLE,
                          new String[]{IDCOLUMN + " AS _id",
                                  FOODCOLUMN
                          },
                          null,null,null,null,null);
                  mSCA = new SimpleCursorAdapter(this,android.R.layout.simple_list_item_1,mCsr,
                          new String[]{FOODCOLUMN},
                          new int[]{android.R.id.text1},0);
                  mFoodList.setAdapter(mSCA);
              } else {
                  Toast.makeText(this,"Unable to open Database.",Toast.LENGTH_LONG);
              }
          }
      
          private SQLiteDatabase openFoodDB() {
              String dbpath = this.getDatabasePath(DBNAME).getPath();
              if (this.getDatabasePath(DBNAME).exists()) {
                  Log.d("OPENFOODDB","Opening already existing Database");
                  return SQLiteDatabase.openDatabase(dbpath,null,SQLiteDatabase.OPEN_READWRITE);
              }
              InputStream is;
              byte[] buffer;
              FileOutputStream db;
              try {
                   is =  this.getAssets().open(DBASSETPATH);
                   buffer = new byte[is.available()];
                   is.read(buffer);
                   is.close();
              } catch (Exception e) {
                  e.printStackTrace();
                  Log.d("OPENFOODDB","Unable to locate or buffer input from assets " + DBASSETPATH);
                  return null;
              }
              // Just in case the databases directory doesn't exist create it.
              File dbmkdir = (this.getDatabasePath(DBNAME)).getParentFile();
              dbmkdir.mkdirs();
              try {
                  db = new FileOutputStream(this.getDatabasePath(DBNAME).getPath());
              } catch (Exception e) {
                  e.printStackTrace();
                  Log.d("OPENFOODDB","Unable to create outputstream for DB at path " + dbpath);
                  try {
                      is.close();
                  } catch (Exception e2) {
                  }
                  return null;
              }
              try {
                  db.write(buffer);
                  db.flush();
                  db.close();
                  is.close();
              } catch (Exception e) {
                  Log.d("OPENFOODDB","Failed to copy asset to DB");
                  e.printStackTrace();
                  return null;
              }
              return SQLiteDatabase.openDatabase(dbpath,null,SQLiteDatabase.OPEN_READWRITE);
          }
      }
      

      注释

      • 如果数据库中不存在资产,则从资产文件复制后,openFoodDB方法将返回SQLiteDatabase.如果出现问题,该方法将返回null.

        Notes

        • the openFoodDB method returns the SQLiteDatabase after copying if from the assets file if the database does not exist. The method will return null if there were issues.

          • 如果数据库存在,则日志将包含类似D/OPENFOODDB: Opening already existing Database
          • 的消息
          • 如果从资产文件复制数据库并成功打开数据库,将没有日志消息.仅在出现问题时才记录消息.
          • 例如,如果缺少资产文件,那么您会在日志中收到一条类似D/OPENFOODDB: Unable to locate or buffer input from assets databases/FoodDB.db的消息,该消息之前会带有堆栈跟踪
          • if the database exists then the log will contain a message like D/OPENFOODDB: Opening already existing Database
          • there will be no log messages if the database was copied from the assets file and opened successfully. Messages will only be logged if there is an issue.
          • if for example the assets file is missing then you would get a message in the log like D/OPENFOODDB: Unable to locate or buffer input from assets databases/FoodDB.db this would be preceded with a stack trace

          例如:-

          03-16 22:17:04.008 1529-1529/? W/System.err: java.io.FileNotFoundException: databases/FoodDB.db
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.content.res.AssetManager.openAsset(Native Method)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:315)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:289)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at fooddb.so49328656populatelistview.MainActivity.openFoodDB(MainActivity.java:63)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at fooddb.so49328656populatelistview.MainActivity.onCreate(MainActivity.java:37)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.app.Activity.performCreate(Activity.java:5008)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.app.ActivityThread.access$600(ActivityThread.java:130)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:99)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.os.Looper.loop(Looper.java:137)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:4745)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at java.lang.reflect.Method.invokeNative(Native Method)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at java.lang.reflect.Method.invoke(Method.java:511)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
          03-16 22:17:04.008 1529-1529/? W/System.err:     at dalvik.system.NativeStart.main(Native Method)
          

          • CursorAdapter需要一列专门命名为 _id 的列,因此需要使用IDCOLUMN + " AS _id".
            • A CursorAdapter requires a column specifically named _id hence the use of IDCOLUMN + " AS _id".
            • 这篇关于如何用资产文件夹中的数据库填充ListView?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆