老铁们,Cursor 用完要 close 大家都知道,怎样优雅地关闭有一点学问。
1 java中一种古老的做法
public String query1(Context context) {
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(MediaStore.Images.Media.getContentUri("internal"), null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID);
if (index >= 0) {
return cursor.getString(index);
}
}
} finally {
if(cursor != null) {
cursor.close();
}
}
return null;
}
这种方法写得还是非常蛋疼的,首先必须声明和赋值分开,然后还要写fanally,finally 当中还必须判空,如果此处是 Stream而不是 cursor,恭喜你,此处close方法还要 try
看看,妈的,正经业务代码没写几行,全用来处理 cursor 了
此时在 try 那一行,lint还会警告你:'try' can use automatic resource management,为了解决这个警告,在 Java 7 我们就要用下面的新方法了
2 现在 java 中应该用这种方法
public String query2(Context context) {
try (Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.getContentUri("internal"), null, null, null, null)) {
int index;
if (cursor != null && cursor.moveToFirst() && ((index = cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID)) >= 0)) {
return cursor.getString(index);
}
}
return null;
}
代码行数直接缩减一半,很爽
try 括号里的对象可以是任何实现 AutoClosable 的接口,Closable 都继承自 AutoClosable
需要说明的是,这种语法还支持多个对象哦
注意第二行,有两个 AutoClosable 对象
public String copyFile1(String from, String to) {
try (InputStream is = new MyFileInputStream(from); OutputStream os = new MyFileOutputStream(to)) {
byte[] bytes = new byte[4096];
int readLen;
while ((readLen = is.read(bytes)) > 0) os.write(bytes, 0, readLen);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
static class MyFileInputStream extends FileInputStream {
public MyFileInputStream(String name) throws FileNotFoundException {
super(name);
}
@Override
public void close() throws IOException {
super.close();
System.out.println("MyFileInputStream#close invoked!");
}
}
static class MyFileOutputStream extends FileOutputStream {
public MyFileOutputStream(String name) throws FileNotFoundException {
super(name);
}
@Override
public void close() throws IOException {
super.close();
System.out.println("MyFileOutputStream#close invoked!");
}
}
可以看到log被打印出来
MyFileOutputStream#close invoked!
MyFileInputStream#close invoked!
Process finished with exit code 0
如果是在 kotlin 中呢
3 kotlin
fun query3(context: Context): String? {
context.contentResolver.query(MediaStore.Images.Media.getContentUri("internal"), null, null, null, null)?.use { cursor ->
var index: Int = -1
if (cursor.moveToFirst() && cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID).also { index = it } >= 0) {
return cursor.getString(index)
}
}
return null
}
在 kotlin 中那毫无疑问就用 use关键字 才能规避 cursor 未关闭的警告,use关键字确保cursor能被关闭
那么copy文件呢
fun copyFile2(from: String, too: String) = File(from).copyTo(File(too))
艾玛,扩展方法,语法糖太甜了,我牙都受不了了
不过其具体实现,还是用 use关键字
this.inputStream().use { input ->
target.outputStream().use { output ->
input.copyTo(output, bufferSize)
}
}
都看到这儿了,不点个赞吗?