在Kotlin中,迭代Android Cursor对象并将结果放入列表的最佳方法是什么?
我自动转换的Java:
val list = ArrayList<String>()
while (c.moveToNext()) {
list.add(getStringFromCursor(c))
}
是否有更惯用的方式?特别是,它可以在一个只读列表的单一分配中完成吗? E.g ....
val list = /*mystery*/.map(getStringFromCursor)
......或其他一些安排,其中列表已分配完整。
答案 0 :(得分:11)
这是我最后使用kotlin.sequences.generateSequence
...
val list = generateSequence { if (c.moveToNext()) c else null }
.map { getStringFromCursor(it) }
.toList()
我的第一次尝试有点短:
val list = (1 .. c.count).map {
c.moveToNext()
getStringFromCursor(c)
}
两个版本都依赖于游标最初位于第一个记录之前。如果不是这样的话,第二个会抛出,而第一个会返回一个较短的列表。
答案 1 :(得分:4)
Cursor
s是懒惰的,所以没有明显的map
。但是Anko(JetBrains的ANdroid KOtlin)确实有一个扩展方法来帮助您映射Cursor
。
该方法称为Cursor.parseList(parser)
。 Here您可以找到它的完整实现。用法应该是直截了当的。 here是关于sqlite的一些官方文档和使用anko解析游标。
答案 2 :(得分:2)
您可以使用此扩展名:
fun <T> Cursor.toArrayList(block: (Cursor) -> T) : ArrayList<T> {
return arrayListOf<T>().also { list ->
if (moveToFirst()) {
do {
list.add(block.invoke(this))
} while (moveToNext())
}
}
}
并使用它:
val list = cursor.toArrayList { getStringFromCursor(it) }
答案 3 :(得分:0)
你的第一个建议是正确的。你不能映射光标。
答案 4 :(得分:0)
类似于Rafols,我创建了一个小函数来解决该问题,因为我不喜欢使用Anko从数组转换为对象。我的解决方案的优点:它会自动关闭游标,它是inline
,因此对性能的影响较小,您可以在parseRow
函数中使用列名。
private inline fun <T> getObjectListFromCursor(cursor: Cursor, parseRow: (Cursor) -> T): List<T> {
return cursor.run {
mutableListOf<T>().also { list ->
if (moveToFirst()) {
do {
list.add(parseRow(this))
} while (moveToNext())
}
close()
}
}
}
您这样称呼它:
val list = getObjectListFromCursor(c, this::getStringFromCursor)
答案 5 :(得分:0)
您可以编写自己的map()
来对isClosed()
进行检查,并在遍历所有行之后安全关闭Cursor
,如下所示:
fun <T> Cursor.map(f: (Cursor) -> T): List<T> {
val items = mutableListOf<T>()
use {
while (!it.isClosed && it.moveToNext()) {
items += f(it)
}
}
return items.toList()
}
样品用量:
val contacts = cursor.map { it.toContact() }
答案 6 :(得分:0)
另一种查看方式
public void makeRequest() {
HttpURLConnection connection = null;
try {
String imageExportServer = "url....";
URL url = new URL(imageExportServer);
connection = (HttpURLConnection)url.openConnection();
Stopwatch stopwatch = Stopwatch.createStarted();
try {
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
try (OutputStream stream = connection.getOutputStream()) {
JsonObject configJson = new JsonObject();
configJson.addProperty("originURL", "url");
configJson.addProperty("url", "url...");
configJson.addProperty("pageOrientation", "someText");
stream.write(Builder().create().toJson(configJson).getBytes());
}
int responseCode = connection.getResponseCode();
if (responseCode != 200) {
//log.warn("Error response: ", responseCode);
}
String fileName = "";
String disposition = connection.getHeaderField("Content-Disposition");
String contentType = connection.getContentType();
int contentLength = connection.getContentLength();
System.out.println("Content-Type = " + contentType);
System.out.println("Content-Disposition = " + disposition);
System.out.println("Content-Length = " + contentLength);
System.out.println("fileName = " + fileName);
// opens input stream from the HTTP connection
InputStream inputStream = connection.getInputStream();
// opens an output stream to save into file
FileOutputStream outputStream = new FileOutputStream("neki.pdf");
int bytesRead = -1;
byte[] buffer = new byte[contentLength];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
FileOutputStream fos = new FileOutputStream("neki.pdf");
fos.write(buffer);
fos.close();
System.out.println("File downloaded");
}
} catch (IOException e) {
//log.warn(e.getMessage(), e);
} finally {
//log.info("Exporting chart of type '%s' took %sms.", "tyoe", stopwatch.elapsed(TimeUnit.MILLISECONDS));
}
} catch (IOException e) {
//log.warn(e.getMessage(), e);
} finally {
if (connection != null) {
try {
connection.disconnect();
} catch (Exception e) {
//log.warn(e.getMessage(), e);
}
}
}
}
答案 7 :(得分:-1)
希望这可以帮助其他人。
var list = ArrayList<HashMap<String, String>>()
if (c != null)
{
c.moveToFirst()
do
{
val temp = HashMap<String, String>()
temp.put("id", c.getString(0))
temp.put("body", c.getString(1))
temp.put("address", c.getString(2))
list.add(temp)
}
while (c.moveToNext())
}