Android上的Kotlin:将光标映射到列表

时间:2016-08-21 16:15:18

标签: android functional-programming kotlin

在Kotlin中,迭代Android Cursor对象并将结果放入列表的最佳方法是什么?

我自动转换的Java:

val list = ArrayList<String>()
while (c.moveToNext()) {
    list.add(getStringFromCursor(c))
}

是否有更惯用的方式?特别是,它可以在一个只读列表的单一分配中完成吗? E.g ....

val list = /*mystery*/.map(getStringFromCursor)

......或其他一些安排,其中列表已分配完整。

8 个答案:

答案 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())
        }