在 Google 的 Android 开发者网站上需要帮助找出适配器 "tutorial"

Need help figuring out an Adapter "tutorial" on Google's Android Developer Site

我目前正在尝试在我的 Android 应用程序中显示数据库信息。
我想要以表格形式显示的数据:

+----------+----------+-----+----------+
| column 1 | column 2 | ... | column n |
+----------+----------+-----+----------+
| xxxx     | xxxx     | ... | nnnn     |
| yyyy     | yyyy     | ... | nnnn     |
| ....     | ....     | ... | nnnn     |
| zzzz     | zzzz     | ... | nnnn     |
+----------+----------+-----+----------+

查看资料HERE,看来我需要使用带有 SimpleCursorAdapter 的 GridView。

因此,我创建了一个扩展 SQLiteOpenHelper 的 DatabaseHelper class。在那个 class 中,我有一个方法 returns 一个查询的游标:

public static final String DATABASE_NAME = "myDatabaseName";
public static final int DATABASE_VERSION = 1;
public static final String TABLE_NAME = "myDatabaseTableName";

public DatabaseHelper(Context context){
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

public static final String MY_QUERY = "SELECT * FROM " + TABLE_NAME;

public Cursor getDataCursor(){
    SQLiteDatabase sqliteDB = this.getReadableDatabase();
    return sqliteDB.rawQuery(MY_QUERY, null);
}

那个 Google 开发页面上 "tutorial" 的一部分指出:

For example, if you want to create a list of people's names and phone numbers, you can perform a query that returns a Cursor containing a row for each person and columns for the names and numbers. You then create a string array specifying which columns from the Cursor you want in the layout for each result and an integer array specifying the corresponding views that each column should be placed

然后有这个代码:

String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};

因此,在我的 MainActivity.java 中,我创建了一个 DatabaseHelper 的新实例,并获得了一个 Cursor:

DatabaseHelper myDBHelper = new DatabaseHelper(this);
Cursor myDataCursor = myDBHelper.getDataCursor();

我想不通的是,上面 Google 的代码片段中的 "ContactsContract" 是什么?我认为这可能是他们的光标,但我的光标没有可用的 "Data" 或 "CommonDataKinds" 方法。我查了一下 Google 的 API 指南页面,看看他们在哪里定义了这些方法,但似乎无法找到它们。在同一个示例中,我也无法弄清楚他们从哪里得到 "R.layout.person_name_and_number"。

感谢您抽出时间阅读。

编辑:

我已将此代码添加到我的代码中 MainActivity.java:

DatabaseHelper myDBHelper = new DatabaseHelper(this);
Cursor myDataCursor = myDBHelper.getDataCursor();
String[] fromColumns = {"_id", "columnA","columnB","...","columnN"};
int[] toViews = {R.id.id_textview, R.id.columnA_textview, R.id.columnB_textview, ... , R.id.columnN_textview};
SimpleCursorAdapter sca = new SimpleCursorAdapter(this, R.layout.my_new_layout, myDataCursor, fromColumns, toViews, 0);
ListView myListView = (ListView) findViewById(R.id.row_of_data);
myListView.setAdapter(sca);

然后我创建了一个名为 my_new_layout.xml 的新视图:

<ListView android:id="@+id/row_of_data">
    <TextView android:id="@+id/id_textview" />
    <TextView android:id="@+id/columnA_textview" />
    <TextView android:id="@+id/columnB_textview" />
    ...
    <TextView android:id="@+id/columnN_textview" />
</ListView>

然后我将新视图添加到 activity_main.xml

<include layout="@layout/"my_new_layout />

但是,现在当我尝试 运行 应用程序时,出现错误:

java.lang.unsupportedoperationexception addview(view, layoutparams) is not supported in adapterview

奇怪的是,我在 activity_main.xml.

中包含了我的新布局

查看 SimpleCursorAdapterdocumentation 及其构造函数,您可以看到

public SimpleCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to, int flags)

参数

  • context: 与此SimpleListItemFactory 关联的ListView 所在的上下文是运行
  • layout:定义此列表项视图的布局文件的资源标识符。布局文件应至少包含 "to"
  • 中定义的命名视图
  • c:数据库游标。如果游标尚不可用,则可以为 null。
  • from:表示要绑定到 UI 的数据的列名列表。如果游标尚不可用,则可以为 null。
  • to:应在"from" 参数中显示列的视图。这些都应该是 TextView。此列表中的前 N ​​个视图被赋予 from 参数中前 N 个列的值。如果游标尚不可用,则可以为 null。
  • flags:用于确定适配器行为的标志,根据 CursorAdapter(Context, Cursor, int)。

fromColumns 是您的 table 的列的名称,您希望从中获取数据

toViews 是你的 TextViews 的 ID,应该在你的行的 XML 布局中(构造函数中的第二个参数 - int layout).

两个数组中的项目数应该相同。

首先,你的SQL命令不应该是这个。 "SELECT * FROM MyDatabase";

您的 table 名称具有误导性,或者您的逻辑有误。

"SELECT * FROM MyDatabase"; 应该(逻辑上)"SELECT * FROM MyTable";

这可能就是您的光标没有返回您所期望的结果的原因。


关于 ContactsContract.CommonDataKinds.Phone.NUMBER 它只是一个包含常量的静态 class。

以下模式允许您将所有字符串放在有组织的位置 class。

这还可以通过允许 IDE 代码自动完成来帮助您不必 'remember' - 每个变量 name/etc。您可以自动完成它们直到完成。这有助于集中您的常量,并且只有一个地方需要更改字符串值。

例如(这只列出了 1 个值)

public class ContactsContract {
    public class CommonDataKinds {
        public class Phone {
            public static final String NUMBER = "number";
        }
    }    

}

更多信息:

这是相关文件的 javadoc:

https://developer.android.com/reference/android/provider/ContactsContract.html

这是该文件的源代码(来自 grep 代码):

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.0_r1/android/provider/ContactsContract.java

(如您所见,我上面的代码片段是正确的,除了我忘记制作每个 class final... 但我很接近)


这是另一个可能更清楚的例子:

我写了这段代码(不是我的回购...代码在我的博士导师的回购中,并在 Coursera 课程中使用 https://www.coursera.org/course/posasoftware

我们的MOOC Schema

A file that uses it(即public,学习者不必写)

如您所见,架构 class 的好处是它允许第 2 个 class 到 'make use of' 架构的内部字符串值,而不必直接处理字符串.这些文件之间仍然存在紧密耦合,但它允许您在一个地方对数据库进行更改(例如修复拼写错误等),而无需遍历整个代码来寻找要替换的字符串。 (也减少了代码中其他地方的拼写错误)。