Android待解决问题及笔记汇总

82 阅读3分钟

0D78D2EC-39DD-4e81-A0AB-B38A15E6A59A.png

E0DE3520-03A3-4234-8267-F8143DC14AD1.png

23EDBE3E-7D78-43f4-8294-224706665B5E.png

  1. Handler内存泄露 未及时处理的message持有handler的强引用; 使用handler.removeMessages(what)销毁消息;

  2. Room索引使用

什么情况下要避免使用索引?

虽然索引的目的在于提高数据库的性能,但这里有几个情况需要避免使用索引。使用索引时,应重新考虑下列准则:

  • 索引不应该使用在较小的表上。
  • 索引不应该使用在有频繁的大批量的更新或插入操作的表上。
  • 索引不应该使用在含有大量的 NULL 值的列上。
  • 索引不应该使用在频繁操作的列上。
  1. Room外键

外键只是保证数据的一致性,并不能给系统性能带来任何好处,在数据量特别大的情况下,每一次约束检查必然导致性能的下降,所以由于外键导致的插入数据变慢会随着数据量的增长而越来越严重

  1. Android计算dip(dp):dp = px * requireContext().resources?.displayMetrics?.density
  2. Android富文本展示官方推荐:SpannedStringSpannableStringSpannableStringBuilder
  3. Android腾讯地图去除logo水印
/**
 * 重写腾讯地图管理SupportMapFragmentFragment类
 * 去除腾讯地图logo水印
 * @author decheng.li 2023/1/13
 */
class MapFragment: SupportMapFragment() {
    override fun onCreateView(
        layoutinflater: LayoutInflater,
        viewgroup: ViewGroup?,
        bundle: Bundle?
    ): View? {
        val mapView: MapView = super.onCreateView(layoutinflater, viewgroup, bundle) as MapView
        mapView.viewTreeObserver?.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                //获取logo水印所在的图层并隐藏该图层,目前logo是第二层图层
                mapView.getChildAt(1)?.visibility = View.INVISIBLE
                mapView.viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        })
        return super.onCreateView(layoutinflater, viewgroup, bundle)
    }
}
  1. kotlin LiveData自定义MutableListLiveData,实现对集合数据元素变动、size变化、及整体数据改变进行实时观察响应:
/**
 * 自定义LiveData,存储集合数据,支持监听数量变化
 */
open class MutableListLiveData<T>(mutableList: MutableList<T>?) {
    companion object {
        private const val START_VERSION = -1
    }
    private var mData: MutableList<T>? = mutableList
    private var mVersion = 0
    private var mSizeVersion = 0
    var mActiveCount = 0
    private var mChangingActiveState = false
    private var mDispatchingValue = false
    private var mDispatchInvalidated = false
    private val mObservers: SafeIterableMap<Observer<Any>, ObserverWrapper> =
        SafeIterableMap<Observer<Any>, ObserverWrapper>()

    init {
        mVersion = START_VERSION + 1
        mSizeVersion = START_VERSION + 1
    }

    fun getData(): MutableList<T>? {
        return mData
    }

    fun setValue(value: MutableList<T>?) {
        assertMainThread("setValue")
        mVersion++
        mData = value
        dispatchingValue(null)
    }

//    fun postValue(value: MutableList<T>?) {
//        super.postValue(value)
//    }

    fun addAll(value: MutableList<T>) {
        assertMainThread("addValue")
        mSizeVersion++
        mData?.addAll(value)
        dispatchingValue(null)
    }

    fun removeValue(value: T) {
        assertMainThread("addValue")
        mSizeVersion++
        mData?.remove(value)
        dispatchingValue(null)
    }

    private fun assertMainThread(methodName: String) {
        check(ArchTaskExecutor.getInstance().isMainThread) {
            ("Cannot invoke " + methodName + " on a background"
                    + " thread")
        }
    }

    @MainThread
    open fun observe(owner: LifecycleOwner, observer: Observer<Any>) {
        assertMainThread("observe")
        if (owner.lifecycle.currentState == Lifecycle.State.DESTROYED) {
            // ignore
            return
        }
        val wrapper = LifecycleBoundObserver(owner, observer)
        val existing: ObserverWrapper? = mObservers.putIfAbsent(observer, wrapper)
        require(!(existing != null && !existing.isAttachedTo(owner))) {
            ("Cannot add the same observer"
                    + " with different lifecycles")
        }
        if (existing != null) {
            return
        }
        owner.lifecycle.addObserver(wrapper)
    }

    @MainThread
    fun observeSize(owner: LifecycleOwner, observer: Observer<Any>) {
        assertMainThread("observeSize")
        if (owner.lifecycle.currentState == Lifecycle.State.DESTROYED) {
            // ignore
            return
        }
        val wrapper = SizeLifecycleBoundObserver(owner, observer)
        val existing: ObserverWrapper? = mObservers.putIfAbsent(observer, wrapper)
        require(!(existing != null && !existing.isAttachedTo(owner))) {
            ("Cannot add the same observer"
                    + " with different lifecycles")
        }
        if (existing != null) {
            return
        }
        owner.lifecycle.addObserver(wrapper)
    }

    private fun dispatchingValue(initiator: ObserverWrapper?) {
        var initiator: ObserverWrapper? = initiator
        if (mDispatchingValue) {
            mDispatchInvalidated = true
            return
        }
        mDispatchingValue = true
        do {
            mDispatchInvalidated = false
            if (initiator != null) {
                considerNotify(initiator)
                initiator = null
            } else {
                val iterator: Iterator<Map.Entry<Observer<Any>, ObserverWrapper?>> =
                    mObservers.iteratorWithAdditions()
                while (iterator.hasNext()) {
                    considerNotify(iterator.next().value)
                    if (mDispatchInvalidated) {
                        break
                    }
                }
            }
        } while (mDispatchInvalidated)
        mDispatchingValue = false
    }

    private fun considerNotify(observer: ObserverWrapper?) {
        if (observer?.mActive == false) {
            return
        }
        if (observer?.shouldBeActive() == false) {
            observer.activeStateChanged(false)
            return
        }
//        if (observer?.mLastVersion!! >= mVersion) {
//            return
//        }
//        observer.mLastVersion = mVersion
        if (observer is SizeLifecycleBoundObserver) {
            if (observer.mLastVersion >= mSizeVersion) {
                return
            }
            observer.mLastVersion = mSizeVersion
            observer.mObserver.onChanged(mData?.size)
        } else {
            if (observer?.mLastVersion!! >= mVersion) {
                return
            }
            observer.mLastVersion = mVersion
            observer.mObserver.onChanged(mData)
        }
    }

    @MainThread
    open fun removeObserver(observer: Observer<Any>) {
        assertMainThread("removeObserver")
        val removed = mObservers.remove(observer) ?: return
        removed.detachObserver()
        removed.activeStateChanged(false)
    }

    private abstract inner class ObserverWrapper constructor(observer: Observer<Any>) {
        val mObserver: Observer<Any>
        var mActive = false
        var mLastVersion = START_VERSION

        init {
            mObserver = observer
        }

        abstract fun shouldBeActive(): Boolean
        open fun isAttachedTo(owner: LifecycleOwner?): Boolean {
            return false
        }

        open fun detachObserver() {}
        fun activeStateChanged(newActive: Boolean) {
            if (newActive == mActive) {
                return
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive
            changeActiveCounter(if (mActive) 1 else -1)
            if (mActive) {
                dispatchingValue(this)
            }
        }


    }

    /**
     * 监听集合重置变化
     */
    private open inner class LifecycleBoundObserver(open val mOwner: LifecycleOwner, observer: Observer<Any>) :
        ObserverWrapper(observer), LifecycleEventObserver {
        override fun shouldBeActive(): Boolean {
            return mOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)
        }

        override fun onStateChanged(
            source: LifecycleOwner,
            event: Lifecycle.Event
        ) {
            var currentState = mOwner.lifecycle.currentState
            if (currentState == Lifecycle.State.DESTROYED) {
                removeObserver(mObserver)
                return
            }
            var prevState: Lifecycle.State? = null
            while (prevState != currentState) {
                prevState = currentState
                activeStateChanged(shouldBeActive())
                currentState = mOwner.lifecycle.currentState
            }
        }

        override fun isAttachedTo(owner: LifecycleOwner?): Boolean {
            return mOwner === owner
        }

        override fun detachObserver() {
            mOwner.lifecycle.removeObserver(this)
        }
    }

    /**
     * 监听集合数据size变化
     */
    private inner class SizeLifecycleBoundObserver(override val mOwner: LifecycleOwner, observer: Observer<Any>) :
        LifecycleBoundObserver(mOwner, observer), LifecycleEventObserver

    @MainThread
    open fun changeActiveCounter(change: Int) {
        var previousActiveCount: Int = mActiveCount
        mActiveCount += change
        if (mChangingActiveState) {
            return
        }
        mChangingActiveState = true
        try {
            while (previousActiveCount != mActiveCount) {
                val needToCallActive = previousActiveCount == 0 && mActiveCount > 0
                val needToCallInactive = previousActiveCount > 0 && mActiveCount == 0
                previousActiveCount = mActiveCount
                if (needToCallActive) {
                    onActive()
                } else if (needToCallInactive) {
                    onInactive()
                }
            }
        } finally {
            mChangingActiveState = false
        }
    }

    protected open fun onInactive() {}
    protected open fun onActive() {}
}