从数据库中提取多级ListView

时间:2012-01-19 22:58:41

标签: android database listview cursor

我正在研究我的第一个Android应用程序并遇到一个问题我似乎无法找到解决方案。我正在尝试使用一系列列表视图设置我的UI,这些列表视图最后将连接到显示需要输入的编辑文本的页面。 IE类别 - >来源 - >标题 - >换句话说,编辑我们将首先显示一个类别列表(音乐,电影等)。然后用户点击让我们说音乐,然后它会列出我的数据库中的艺术家。然后点击艺术家,它将在我的数据库中显示他们的歌曲。我有设置atm它将显示我设置的游标,但是我在设置我的程序时遇到问题,看看用户点击了什么,并给出结果/显示光标,其中包含我想要显示的数据。

public class dbadapter extends SQLiteOpenHelper {

     //The Android's default system path of your application database.
   public static final String DB_PATH = "/data/data/wanted.pro.madlibs/databases/";
   public static final String DB_NAME = "madlib";
   public static final int DB_VERSION = 1;
   private static final String TAG = "dbadapter";

   //database variables
   public static final String  KEY_ID = "_id";
   public static final String  KEY_CATEGORYDESC = "categorydesc";
   public static final String KEY_TITLE = "titlekey";
   public static final String KEY_TITLEDESC = "titledesc";
   public static final String KEY_TITLESTORY = "titlestory";
   public static final String KEY_SOURCEDESC = "sourcedesc";
   public static final String KEY_SOURCE = "sourcekey";
   public static final String KEY_CATEGORY = "categorykey";

   //table variables
   public static final String CATEGORY_TABLE = "category";
   public static final String SOURCE_TABLE = "source";
   public static final String TITLE_TABLE = "title";

   private dbadapter mydbhelper;
   private static SQLiteDatabase myDataBase; 


   @Override
   public void onOpen(SQLiteDatabase myDatabase)
   {
     super.onOpen(myDatabase);
     if (!myDatabase.isReadOnly())
     {
       // Enable foreign key constraints
       myDatabase.execSQL("PRAGMA foreign_keys=ON;");
     }
   }

   /**
    * Constructor
    * Takes and keeps a reference of the passed context in order to access to the application assets and resources.
    * @param context
    */

       private final Context mCtx;
    public dbadapter(Context context) {

    super(context, DB_NAME, null, DB_VERSION);
       this.mCtx = context;
   }    

 /**
    * Creates a empty database on the system and rewrites it with your own database.
    * */
   public void createDataBase() throws IOException{

    boolean dbExist = checkDataBase();

    if(dbExist){
        //do nothing - database already exist
    }else{

        //By calling this method and empty database will be created into the default system path
              //of your application so we are gonna be able to overwrite that database with our database.
        this.getReadableDatabase();

        try {

            copyDataBase();

        } catch (IOException e) {

            throw new Error("Error copying database");

        }
    }


   }

   /**
    * Check if the database already exist to avoid re-copying the file each time you open the application.
    * @return true if it exists, false if it doesn't
    */
   private boolean checkDataBase(){

    SQLiteDatabase checkDB = null;

    try{
        String myPath = DB_PATH + DB_NAME;
        checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

    }catch(SQLiteException e){

        //database does't exist yet.

    }

    if(checkDB != null){

        checkDB.close();

    }

    return checkDB != null ? true : false;
   }

   /**
    * Copies your database from your local assets-folder to the just created empty database in the
    * system folder, from where it can be accessed and handled.
    * This is done by transferring bytestream.
    * */
   private void copyDataBase() throws IOException{

    //Open your local db as the input stream
    InputStream myInput = mCtx.getAssets().open(DB_NAME);

    // Path to the just created empty db
    String outFileName = DB_PATH + DB_NAME;

    //Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    //transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer))>0){
        myOutput.write(buffer, 0, length);
    }

    //Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();

   }

   public void openDataBase() throws SQLException{

    //Open the database
       String myPath = DB_PATH + DB_NAME;
    myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

   }

   @Override
    public synchronized void close() {

        if(myDataBase != null)
            myDataBase.close();

        super.close();

    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data");
        db.execSQL("DROP TABLE IF EXISTS category");
        onCreate(db);
    }

    public dbadapter open() throws SQLException {
        mydbhelper = new dbadapter (mCtx);
        myDataBase = mydbhelper.getWritableDatabase();
        return this;
    }



    // Add your public helper methods to access and get content from the database.
      // You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
      // to you to create adapters for your views.

    // retrieves all the categories
      public static Cursor getAllCategories() 
        {
            return myDataBase.query(CATEGORY_TABLE, new String[] {
                    KEY_ID, KEY_CATEGORY,
                    KEY_CATEGORYDESC,
                    }, 
                    null, null, null, null, KEY_CATEGORYDESC);

        }
    // retrieves all the titles
          public Cursor getAllTitles() 
            {
                return myDataBase.query(TITLE_TABLE, new String[] {
                        KEY_ID, 
                        KEY_TITLE,
                        KEY_TITLEDESC,
                        KEY_TITLESTORY,
                        }, 
                        null, null, null, null, KEY_TITLEDESC);

            }
        // retrieves all the sources
          public  Cursor getAllSources() 
            {
                return myDataBase.query(SOURCE_TABLE, new String[] {
                        KEY_ID, 
                        KEY_SOURCE,
                        KEY_SOURCEDESC,
                        }, 
                        null, null, null, null, KEY_SOURCEDESC);

            }

以下是我的适配器

的代码
public class categories extends ListActivity {
    /** Called when the activity is first created. */
    private dbadapter mydbhelper;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.category_list);
        mydbhelper = new dbadapter(this);
        mydbhelper.open();
        fillData();
    }
    private void fillData() {
            Cursor c = mydbhelper.getAllCategories();
            startManagingCursor(c);

     // Create an array to specify the fields we want to display in the list (TITLE,DATE,NUMBER)
        String[] from = new String[] {dbadapter.KEY_CATEGORYDESC};

        // an array of the views that we want to bind those fields to (in this case text1,text2,text3)
        int[] to = new int[] {R.id.text1};

        // Now create a simple cursor adapter and set it to display
        SimpleCursorAdapter adapter = 
            new SimpleCursorAdapter(this, R.layout.cate_row, c, from, to);
        setListAdapter(adapter);
        }
@Override
protected void onListItemClick(ListView list, View v, int position, long id)
{
    super.onListItemClick(list, v, position, id);
    final Intent intent = new Intent(this, source.class);

    startActivityForResult(intent, position);
    }
}

这将是我创建数据库表的SQL日志

CREATE TABLE category(
_id INT,  
categorykey INT,
  categorydesc TEXT,
   PRIMARY KEY(_id)
);
CREATE TABLE source(
_id INT,  
sourcekey INT,
  sourcedesc TEXT,
   PRIMARY KEY(_id)
);
CREATE TABLE title(
_id INT,  
titlekey INT,
  titledesc TEXT,
titlestory TEXT,
   PRIMARY KEY(_id)
);
CREATE TABLE userword(
_id INT,  
titlekey INT,
  userword TEXT,
   PRIMARY KEY(_id), FOREIGN KEY(titlekey) REFERENCES title(titlekey)
);
CREATE TABLE category_title(
titlekey INT,
  categorykey INT,
  FOREIGN KEY(titlekey) REFERENCES title(titlekey), FOREIGN KEY (categorykey) REFERENCES category(categorykey)
);
CREATE TABLE source_title(
titlekey INT,
  sourcekey INT,
  FOREIGN KEY(titlekey) REFERENCES title(titlekey), FOREIGN KEY (sourcekey) REFERENCES source(sourcekey)
);
CREATE TABLE source_category(
sourcekey INT,
  categorykey INT,
  FOREIGN KEY(categorykey) REFERENCES category(categorykey), FOREIGN KEY (sourcekey) REFERENCES source(sourcekey)
);

我知道我唯一正确的游标是类别,因为它是数据库表中唯一不会被之前选择过滤的数据。

2 个答案:

答案 0 :(得分:1)

我使用类似的东西,我使用单独的表来保存我的列表。我不会像你将要使用的那样预先填充。我有一个列表视图由一个表列表填充,当您单击列表中的项目时,它会弹出另一个列表视图,该列表视图由所选表格中的条目填充。那是你要找的那种东西吗?

修改

再看一遍,

CREATE TABLE category(
_id INT,  
categorykey INT,
categorydesc TEXT,
PRIMARY KEY(_id)
);
CREATE TABLE source(
_id INT,  
sourcekey INT,
sourcedesc TEXT,
PRIMARY KEY(_id)
);

etc为每个创建一个单独的表,因此您需要更改表以获取其他列表。 public static final String CATEGORY_TABLE = "category";只查询表类别以查询表格来源public static final String CATEGORY_TABLE = "source";

我所做的是使用列表视图中设置的变量

String click = l.getItemAtPosition(position).toString();
table = click;
<{1>} onListItemClick() tablepublic static String table;,然后为您的查询使用table而不是

答案 1 :(得分:1)

如果我的方案正确,你想知道如何确定选择了哪个对象(特别是哪个条目)。这可以很直接地完成,比尔加里给出了一个暗示。有两种选择:

  1. 使用“位置”作为指示器在哪里移动 目前的curso。根据您当前的光标和您的位置 然后深入查询一层。
  2. 使用“代理模式”明确区分您的 逻辑和数据库数据。我是这样做的。您创建一个新类 表示数据库条目,例如类别。 而不是填充您的适配器与纯数据库数据插入那些 对象(所谓的代理)。那些代理人都有参考 他们相应的数据库条目(通过光标)。点击时 你可以在这个地方询问适配器的项目。 那么你可以问这个项目你引用的数据条目。那么你 在该数据集的下一层(艺术家...)中查询您的数据库。
  3. 对于正确的查询,您应该使用SELECT ... WHERE语句,您可以使用query()方法轻松实现该语句。但是,当你使用这种方法我认为你知道如何做到这一点。

相关问题