目錄
- 前言
- 正文
- 1. If a binding adapter provides the setter, check that the adapter is annotated correctly and that the parameter type matches.
- 2. 在 RecyclerView.Adapter 的 onBindViewHolder 方法中使用 Databinding,導致列表條目重複
- 3. kotlin.TypeCastException: null cannot be cast to non-null type com.readbook.chinesepoetry.data.model.Response
前言
記錄開發中遇到的 bug,不再讓自己重複地被同樣的 bug 折磨。
正文
1. If a binding adapter provides the setter, check that the adapter is annotated correctly and that the parameter type matches.
時間:2019年12月29日12:04:20
問題描述:
在 kotlin 工程中,使用 Databinding 的 @BindingAdapter 報錯:
Cannot find a setter for <androidx.recyclerview.widget.RecyclerView app:items> that accepts parameter type 'androidx.lifecycle.LiveData<java.util.List<com.readbook.chinesepoetry.data.model.PoetryBean>>'
If a binding adapter provides the setter, check that the adapter is annotated correctly and that the parameter type matches.
問題解決:
在 build.gradle 文件中添加:
apply plugin: 'kotlin-kapt'
2. 在 RecyclerView.Adapter 的 onBindViewHolder 方法中使用 Databinding,導致列表條目重複
時間:2019年12月29日16:40:29
問題描述:
class RecommendAdapter(private val viewModel: RecommendViewModel) :
ListAdapter<PoetryBean, RecommendViewHolder>(PoetryBeanDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecommendViewHolder {
val binding = RecommendRecycleItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return RecommendViewHolder(binding)
}
override fun onBindViewHolder(holder: RecommendViewHolder, position: Int) {
val item = getItem(position)
holder.bindItem(item)
}
class RecommendViewHolder(private val binding: RecommendRecycleItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bindItem(item: PoetryBean) {
Timber.d("item=$item")
with(item) {
binding.tvName.text = name + Integer.toString(id)
binding.tvDynastyPoet.text = itemView.context.getString(R.string.common_dynasty_poet, dynasty, poet)
binding.tvContent.text = Html.fromHtml(content)
}
}
}
}
問題分析:
對比查看 android-architecture 的代碼,發現會在 bindItem() 方法中最後一行再調用一次:
binding.executePendingBindings()
增加這一行代碼後,解決了問題。但還是要再詳細瞭解一下。
再去查看一下官方文檔的說明:https://developer.android.google.cn/topic/libraries/data-binding/generated-binding#immediate_binding
When a variable or observable object changes, the binding is scheduled to change before the next frame. There are times, however, when binding must be executed immediately. To force execution, use the executePendingBindings() method.
並且官方也給了實例代碼 https://developer.android.google.cn/topic/libraries/data-binding/generated-binding#dynamic_variables :
override fun onBindViewHolder(holder: BindingHolder, position: Int) {
item: T = items.get(position)
holder.binding.setVariable(BR.item, item);
holder.binding.executePendingBindings();
}
參考:https://stackoverflow.com/questions/53043412/android-why-use-executependingbindings-in-recyclerview
3. kotlin.TypeCastException: null cannot be cast to non-null type com.readbook.chinesepoetry.data.model.Response<com.readbook.chinesepoetry.data.model.RecommendListBean>
時間:2020年1月5日21:30:35
問題描述:
object CacheUtil {
private val cache = ACache.get(File(Utils.getApp().filesDir, "ACache"))
private const val RECOMMEND_LIST = "recommend_list"
fun getRecommendList(page: Int): Response<RecommendListBean>? {
return cache.getAsObject(RECOMMEND_LIST + page) as Response<RecommendListBean>
}
}
第一次取出 cache.getAsObject(RECOMMEND_LIST + page)
爲 null
,轉爲 Response<RecommendListBean>
這個非空類型時報錯的。
解決辦法:
把代碼改爲:
return cache.getAsObject(RECOMMEND_LIST + page) as Response<RecommendListBean>?
4. Java:Inner class cannot have static declaration
時間:2020年1月11日13:17:22
問題描述:
public class Apply {
class ApplyTest {
// 下面的方法編譯報錯:Inner class cannot have static declaration
public static void main(String[] args) throws Exception {
List<Shape> shapes = new ArrayList<>();
}
}
}
解決辦法:
public class Apply {
static class ApplyTest {
// 下面的方法編譯報錯:Inner class cannot have static declaration
public static void main(String[] args) throws Exception {
List<Shape> shapes = new ArrayList<>();
}
}
}
5. javax.net.ssl.SSLHandshakeException(Chain validation failed)
時間:2020年1月19日10:13:44
問題描述:
我在應用裏面使用 Glide 加載 github 上存儲的圖片資源,可是在一個手機上原來加載出來,後來卻加載不出來了。
2020-01-29 09:57:22.392 9043-9043/com.readbook.chinesepoetry W/Glide: Load failed for https://raw.githubusercontent.com/xxx/poetry/master/image/image_248.jpg with size [192x192]
class com.bumptech.glide.load.engine.GlideException: Failed to load resource
There was 1 cause:
javax.net.ssl.SSLHandshakeException(Chain validation failed)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 1): class com.bumptech.glide.load.engine.GlideException: Fetching data failed, class java.io.InputStream, REMOTE
There was 1 cause:
javax.net.ssl.SSLHandshakeException(Chain validation failed)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 1): class com.bumptech.glide.load.engine.GlideException: Fetch failed
There was 1 cause:
javax.net.ssl.SSLHandshakeException(Chain validation failed)
call GlideException#logRootCauses(String) for more detail
Cause (1 of 1): class javax.net.ssl.SSLHandshakeException: Chain validation failed
2020-01-29 09:57:22.396 9043-9043/com.readbook.chinesepoetry I/Glide: Root cause (1 of 1)
javax.net.ssl.SSLHandshakeException: Chain validation failed
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:355)
at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:192)
at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:149)
at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:112)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:184)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:461)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(Unknown Source:0)
at com.bumptech.glide.load.data.HttpUrlFetcher.loadDataWithRedirects(HttpUrlFetcher.java:100)
at com.bumptech.glide.load.data.HttpUrlFetcher.loadData(HttpUrlFetcher.java:56)
at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100)
at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.startNextOrFail(MultiModelLoader.java:164)
at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.onLoadFailed(MultiModelLoader.java:154)
at com.bumptech.glide.load.data.HttpUrlFetcher.loadData(HttpUrlFetcher.java:62)
at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100)
at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279)
at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:431)
Caused by: java.security.cert.CertificateException: Chain validation failed
at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:705)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:537)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:558)
at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:626)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:493)
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:416)
at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:337)
at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:88)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:203)
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:592)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:351)
at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:192)
at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:149)
at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:112)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:184)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:461)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(Unknown Source:0)
at com.bumptech.glide.load.data.HttpUrlFetcher.loadDataWithRedirects(HttpUrlFetcher.java:100)
at com.bumptech.glide.load.data.HttpUrlFetcher.loadData(HttpUrlFetcher.java:56)
at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100)
at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.startNextOrFail(MultiModelLoader.java:164)
at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.onLoadFailed(MultiModelLoader.java:154)
at com.bumptech.glide.load.data.HttpUrlFetcher.loadData(HttpUrlFetcher.java:62)
at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100)
at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:63)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279)
at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:431)
Caused by: java.security.cert.CertPathValidatorException: Response is unreliable: its validity interval is out-of-date
2020-01-29 09:57:22.399 9043-9043/com.readbook.chinesepoetry I/Glide: at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:133)
at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:225)
at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:143)
at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79)
at java.security.cert.CertPathValidator.validate(CertPathValidator.java:301)
at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:701)
... 39 more
Caused by: java.security.cert.CertPathValidatorException: Response is unreliable: its validity interval is out-of-date
at sun.security.provider.certpath.OCSPResponse.verify(OCSPResponse.java:619)
at sun.security.provider.certpath.RevocationChecker.checkOCSP(RevocationChecker.java:709)
at sun.security.provider.certpath.RevocationChecker.check(RevocationChecker.java:363)
at sun.security.provider.certpath.RevocationChecker.check(RevocationChecker.java:337)
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:125)
... 44 more
Suppressed: java.security.cert.CertPathValidatorException: Could not determine revocation status
at sun.security.provider.certpath.RevocationChecker.buildToNewKey(RevocationChecker.java:1092)
at sun.security.provider.certpath.RevocationChecker.verifyWithSeparateSigningKey(RevocationChecker.java:910)
at sun.security.provider.certpath.RevocationChecker.checkCRLs(RevocationChecker.java:577)
at sun.security.provider.certpath.RevocationChecker.checkCRLs(RevocationChecker.java:465)
at sun.security.provider.certpath.RevocationChecker.check(RevocationChecker.java:394)
... 46 more
解決辦法:原來是手機時間的問題,修改爲當前時間,解決了這個問題。
最後
代碼出錯了,關鍵是要仔細查看日誌。能夠仔細地查看日誌,就離解決問題很近了。