2012-08-15 136 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

相關問題