如何在列表中包含其他数据库列?

时间:2012-08-15 18:49:49

标签: android database sqlite listview android-listview

我正在使用Mimir的Android教程#10,关于在列表中显示预先填充的数据库中的数据。在他们的数据库中,它们有四列,即:(1)ingredient_description,(2)in_stock,(3)_id和(4)ingredient_name。但是,在其列表中,它们仅显示来自ingredient_name列的数据。例如,他们的列表看起来像这样......





但我要做的是连续显示所有四列的数据,如此......



描述:冷冻水
ID:1
有货:是的



描述:H2O
ID:2
有货:是的



本教程使用bindView和newView,并根据他们的评论,“这使我们的代码更清晰,并且是更好的方法。”

我花了很多时间研究这个问题,但我还没弄清楚如何从数据库中获取这三个额外的列以显示在行中。以下是原始代码以及我所做的一些更改(我的更改在注释中注明* * *)。

我知道我仍然缺少某些东西,但那就是我被困住的地方。有人可以告知缺少什么,以显示这三个额外列中的数据?如果可能的话,请告诉我具体缺少什么/如何修复而不是指向我的教程(我已经看了很多,不幸的是,没有什么能够回答我的问题)。还请记住,示例代码使用bindView和newView,因此需要使用它。非常感谢您的帮助。

package com.mimirsoft.tutorial10; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.util.Locale; 
import android.content.Context; 
import android.database.Cursor; 
import android.database.SQLException; 
import android.database.sqlite.SQLiteException; 
import android.database.sqlite.SQLiteOpenHelper; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteQueryBuilder; 
import android.util.Log; 
class IngredientHelper extends SQLiteOpenHelper { 
//we declare a bunch of useful constants 
//the should be pretty obvious what they are! 
private static final String DATABASE_PATH = "/data/data/com.mimirsoft.tutorial10/databases/"; 
private static final String DATABASE_NAME="ingredients.db"; 
private static final int SCHEMA_VERSION=1; 
public static final String TABLE_NAME = "Ingredients"; 
public static final String COLUMN_ID = "_id"; 
public static final String COLUMN_TITLE = "ingredient_name"; 

//* * * MY ADD * * * 
public static final String COLUMN_TITLE2 = "ingredient_description";

//* * * MY ADD * * * 
public static final String COLUMN_TITLE3 = "in_stock";


public SQLiteDatabase dbSqlite; 
private final Context myContext; 
public IngredientHelper(Context context) { 
super(context, DATABASE_NAME, null, SCHEMA_VERSION); 
this.myContext = context; 
// check if exists and copy database from resource 
//createDB(); 
} 
@Override 
public void onCreate(SQLiteDatabase db) { 
// check if exists and copy database from resource 
} 
@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
} 
public void createDatabase() { 
createDB(); 
} 
private void createDB() { 
boolean dbExist = DBExists(); 
if (!dbExist) { 
//By calling this method we create an empty database into the default system location 
//We need this so we can overwrite that database with our database. 
this.getReadableDatabase(); 
//now we copy the database we included! 
copyDBFromResource(); 
} 
} 
private boolean DBExists() { 
SQLiteDatabase db = null; 
try { 
String databasePath = DATABASE_PATH + DATABASE_NAME; 
db = SQLiteDatabase.openDatabase(databasePath, null, 
SQLiteDatabase.OPEN_READWRITE); 
db.setLocale(Locale.getDefault()); 
db.setLockingEnabled(true); 
db.setVersion(1); 
} catch (SQLiteException e) { 
Log.e("SqlHelper", "database not found"); 
} 
if (db != null) { 
db.close(); 
} 
return db != null ? true : false; 
} 
private void copyDBFromResource() { 
InputStream inputStream = null; 
OutputStream outStream = null; 
String dbFilePath = DATABASE_PATH + DATABASE_NAME; 
try { 
inputStream = myContext.getAssets().open(DATABASE_NAME); 
outStream = new FileOutputStream(dbFilePath); 
byte[] buffer = new byte[1024]; 
int length; 
while ((length = inputStream.read(buffer)) > 0) { 
outStream.write(buffer, 0, length); 
} 
outStream.flush(); 
outStream.close(); 
inputStream.close(); 
} catch (IOException e) { 
throw new Error("Problem copying database from resource file."); 
} 
} 
public void openDataBase() throws SQLException { 
String myPath = DATABASE_PATH + DATABASE_NAME; 
dbSqlite = SQLiteDatabase.openDatabase(myPath, null, 
SQLiteDatabase.OPEN_READWRITE); 
} 
@Override 
public synchronized void close() { 
if (dbSqlite != null) 
{ 
dbSqlite.close(); 
} 
super.close(); 
} 
public Cursor getCursor() { 
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); 
queryBuilder.setTables(TABLE_NAME); 

// * * * MY CHANGE - CHANGED FROM... * * * 
//String[] asColumnsToReturn = new String[] { COLUMN_ID, COLUMN_TITLE}; 
//* * * TO... * * * 
//String[] asColumnsToReturn = new String[] { COLUMN_ID, COLUMN_TITLE, COLUMN_TITLE2, COLUMN_TITLE3}; 

//make sure you get your search by string pass correctly! 
Cursor mCursor = queryBuilder.query(dbSqlite, asColumnsToReturn, null, 
null, null, null, "ingredient_name ASC"); 
return mCursor; 
} 
public String getName(Cursor c) { 
return(c.getString(1)); 
} 
} 

和...

package com.mimirsoft.tutorial10; 
import android.app.Activity; 
import android.content.Context; 
import android.database.Cursor; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.CursorAdapter; 
import android.widget.ListView; 
import android.widget.TextView; 
//This tutorial introduces the CursorAdaptor, explains how it is different 
//from the Array Adapter, and also introduces the database functionality. 
//We will build a ListView from a Database of cocktail Ingredients 
public class Tutorial10 extends Activity { 
private IngredientHelper dbIngredientHelper = null; 
private Cursor ourCursor = null; 
private IngredientAdapter adapter=null; 
public void onCreate(Bundle savedInstanceState) { 
try 
{ 
super.onCreate(savedInstanceState); 
setContentView(R.layout.main); 
//this is our ListView element, obtained by id from our XML layout 
ListView myListView = (ListView)findViewById(R.id.myListView); 
//create our database Helper 
dbIngredientHelper=new IngredientHelper(this); 
//we call the create right after initializing the helper, just in case 
//they have never run the app before 
dbIngredientHelper.createDatabase(); 
// 
//open the database!! Our helper now has a SQLiteDatabase database object 
dbIngredientHelper.openDataBase(); 
//get our cursor. A cursor is a pointer to a dataset, in this case 
//a set of results from a database query 
ourCursor=dbIngredientHelper.getCursor(); 
//tell android to start managing the cursor, 
//we do this just incase our activity is interrupted or ends, we want the activity 
//to close and deactivate the cursor, as needed 
startManagingCursor(ourCursor); 
//create our adapter 
adapter=new IngredientAdapter(ourCursor); 
//set the adapter!!! 
myListView.setAdapter(adapter); 
} 
catch (Exception e) 
{ 
// this is the line of code that sends a real error message to the log 
Log.e("ERROR", "ERROR IN CODE: " + e.toString()); 
// this is the line that prints out the location in 
// the code where the error occurred. 
e.printStackTrace(); 
} 
} 
class IngredientAdapter extends CursorAdapter { 
IngredientAdapter(Cursor c) { 
super(Tutorial10.this, c); 
} 
@Override 
//this is a CusorAdapter 
//instead of Using a getView and if(row==null) 
// we use bindView and newView calls 
//we can get away with this because CursorAdapters have 
//a default implementation of getView that calls bindView and newView 
//as needed. This makes our code a bit cleaner, and is the better way to 
//do this. 
public void bindView(View row, Context ctxt, 
Cursor c) { 
IngredientHolder holder=(IngredientHolder)row.getTag(); 
holder.populateFrom(c, dbIngredientHelper); 
} 
@Override 
public View newView(Context ctxt, Cursor c, 
ViewGroup parent) { 
LayoutInflater inflater=getLayoutInflater(); 
View row=inflater.inflate(R.layout.row, parent, false); 
IngredientHolder holder=new IngredientHolder(row); 
row.setTag(holder); 
return(row); 
} 
} 
static class IngredientHolder { 
private TextView name=null; 
IngredientHolder(View row) { 
name=(TextView)row.findViewById(R.id.ingredientText); 
} 
void populateFrom(Cursor c, IngredientHelper r) { 
name.setText(r.getName(c)); 
} 
} 
}

2 个答案:

答案 0 :(得分:0)

简单的方法是,您可以在字符串中每行的末尾添加换行符。这会打破你想要的字符串。这样做的不利之处在于你无法分别为每一行设置样式。

更好的方法是创建一个布局并将每个字符串添加为文本视图。 Android API演示中有一个示例,即Views / Lists / 4。 ListAdapter。因此,将其添加到您的设备或在模拟器上运行它。 包名是com.example.android.apis.view,类是List4.java。

这是API示例中的子类。

/**
 * We will use a SpeechView to display each speech. It's just a LinearLayout
 * with two text fields.
 *
 */
private class SpeechView extends LinearLayout {
    public SpeechView(Context context, String title, String words) {
        super(context);

        this.setOrientation(VERTICAL);

        // Here we build the child views in code. They could also have
        // been specified in an XML file.

        mTitle = new TextView(context);
        mTitle.setText(title);
        addView(mTitle, new LinearLayout.LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));

        mDialogue = new TextView(context);
        mDialogue.setText(words);
        addView(mDialogue, new LinearLayout.LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
    }

答案 1 :(得分:0)

我会尝试类似的东西。传递光标并使用整数选择所需的列,并将数据保存到变量中。

private void getName(c){

 name.setText(c.getString(0)
 name2.setText(c.getString(1)
 name3.setText(c.getString(2)
 name4.setText(c.getString(3)

}

然后只需在布局中添加更多文本视图,并使用db中的字符串设置文本。