2012-08-15 125 views
0

我正在与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)); 
} 
} 
} 

回答

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)); 
    } 
+0

感谢您的回复。我不确定我是如何从数据库中获得三个额外列以显示在列表中的。 – Dev1345 2012-08-15 22:02:53

0

我会尝试类似这样的事情。传递光标并用一个整数选择你想要的列,并将数据保存到变量中。

私人无效的getName(C){

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

}

然后,只需添加更多的文字意见,你的布局,并设置自己的文字时,将字符串从数据库中。

+0

感谢您的回复。请说明该代码的放置位置。此外,我仍然离开公共字符串getName(光标c){返回(c.getString(1)); }原样或是否也需要修改?你能否在上面的示例代码中阐明它如何与bindView/getTag和newView/setTag一起工作?我想我只是没有看到它将如何拿起额外的数据库列来显示。对不起,我的无知......我试图围绕这整个事情,但它只是没有点击我。谢谢你的帮助。 – Dev1345 2012-08-16 18:18:04

相关问题