Android 开发中遇到的 bug(11)

前言

记录开发中遇到的 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

解决办法:原来是手机时间的问题,修改为当前时间,解决了这个问题。

最后

代码出错了,关键是要仔细查看日志。能够仔细地查看日志,就离解决问题很近了。

发布了78 篇原创文章 · 获赞 46 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/willway_wang/article/details/103751975