Một số bugs và tips thường gặp trong Android
Bài đăng này đã không được cập nhật trong 2 năm
1. Dùng HttpURLConnection
- Khi dùng HttpURLConnection để connect tới một URL thì lưu ý, URL mình dùng phải là "https". Ở đây, mình dùng để mở đường dẫn tải audio từ một link.
private fun download(url: String) {
var exception: Exception? = null
var fos: FileOutputStream? = null
var myPath: File? = null
var connection: HttpURLConnection? = null
var input: BufferedInputStream? = null
try {
myPath = File("audios", "home.mp3")
if (!myPath.exists()) {
connection = URL(url).openConnection() as HttpURLConnection
connection.connect()
input = BufferedInputStream(URL(url).openStream())
fos = FileOutputStream(myPath)
val data = ByteArray(LessonTopicFragment.SIZE_BYTE)
var count: Int = input.read(data)
while (count != -1) {
fos.write(data, 0, count)
count = input.read(data)
}
}
} catch (e: Exception) {
exception = e
} finally {
fos?.flush()
fos?.close()
input?.close()
connection?.disconnect()
}
}
Lưu ý: Trong file Android.Manifest cần khai báo thêm thuộc tính : android:usesCleartextTraffic="true"
trong thẻ application.
Trong hàm download trên, nếu như truyền vào một url với "http" thì sẽ vẫn download được file, nhưng có một bug ở đây đó là ta chỉ down được đúng một lần với lượng data bằng biến count. Khi thay http sang https thì ta down được file hoàn chỉnh.
2. Dùng ListAdapter
- Khi dùng với ListAdapter thì muốn cập nhật được list một cách chính xác nhất nên tạo một list mới với data đã được cập nhật rồi, và submit lits mới đó. khi dùng với ListAdapter thì kể cả có gọi notify data cũng không thể update được UI.
3. Type Any hoặc List trong Kotlin
Khi sử dụng các type Any hoặc List trong Kotlin, có thể sẽ gặp exception này:
java.lang.IllegalArgumentException: Parameter type must not include a type variable or wildcard
Ví dụ khi POST một trường như sau bằng Retrofit, sẽ gặp exception phía trên:
@POST("speech/practice")
@FormUrlEncoded
fun uploadLog(
@Field("alignment") alignment: List<List<Float>>? = null
)
Lí do vì khi compile Kotlin đã chuyển các type này về kiểu wildcard ? nên JVM không cho phép dùng làm param
Ví dụ khi compile, biến alignment sẽ chuyển thành kiểu
List<? extends List<Float>>
Để khắc phục, mọi người chỉ cần thêm @JvmSuppressWildcards vào phía trước nơi định kiểu, hàm, hoặc class đều được (tất nhiên mỗi nơi có scope khác nhau)
@Field("alignment") alignment: List<@JvmSuppressWildcards List<Float>>? = null
Link tham khảo: https://stackoverflow.com/questions/45409461/the-generic-parameters-any-of-kotlin-are-converted-to-wildcards https://adavis.info/2017/08/jvmsuppresswildcards-biggest-annoyance-kotlin.html
4. Index trong List
Khi làm việc với list trong 1 số trường hợp có thể muốn get phần thử theo index nhưng không chắc index đó có nằm trong range của list hay không. Thường thi ta sẽ check bằng if else, hơi dài 1 tí. Để ngắn gọn hơn thì Kotlin đã hỗ trợ ta với hàm có sẵn getOrNull(index)
val list = ArrayList<String>()
val t = list.getOrNull(2)
output: t = null vì list không có phần tử index = 2
5. Unit test
Khi viết UT có case này khả năng gây lỗi mọi người tham khảo để tránh nhé:
- Nếu test cho ViewModel mà có dùng fun init() thì trong class test phải mock cho các phần cần thiết trước khi khởi tạo đối tượng vm. (thường là làm trong fun @before)
- Vì khi khởi tạo vm, fun được dùng trong init() sẽ chạy luôn và gây lỗi NullPointer.
Cảm ơn mọi người đã đón đọc !
All rights reserved