在5.0系统上头像展示背景黑块的问题

最近是比较懒了,时间是有,代码也不想碰了,开源项目也分析了几个, 断断续续的也没完成,哎。闲话少说了。

在开发过程中,遇到在Android5.0系统及以上的系统上,头像会有黑块的问题,就是在圆形头像的后面有个矩形的黑块,

通常的一些解决方法就是改为非硬加速等等,都试过了,没有效果。最后使用了RecyclingImageView解决了此问题,

具体原因没仔细查看, 应该是图片缓存的问题,没有及时释放。

这个demo源码可以在Android给的samples中找到,在AS中,可以直接导入这个demo。前提是得连外网,一般需要翻墙。

下面是关键代码:

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.displayingbitmaps.ui;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;

import com.example.android.displayingbitmaps.util.RecyclingBitmapDrawable;

/**
 * Sub-class of ImageView which automatically notifies the drawable when it is
 * being displayed.
 */
public class RecyclingImageView extends ImageView {

    public RecyclingImageView(Context context) {
        super(context);
    }

    public RecyclingImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * @see android.widget.ImageView#onDetachedFromWindow()
     */
    @Override
    protected void onDetachedFromWindow() {
        // This has been detached from Window, so clear the drawable
        setImageDrawable(null);

        super.onDetachedFromWindow();
    }

    /**
     * @see android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)
     */
    @Override
    public void setImageDrawable(Drawable drawable) {
        // Keep hold of previous Drawable
        final Drawable previousDrawable = getDrawable();

        // Call super to set new Drawable
        super.setImageDrawable(drawable);

        // Notify new Drawable that it is being displayed
        notifyDrawable(drawable, true);

        // Notify old Drawable so it is no longer being displayed
        notifyDrawable(previousDrawable, false);
    }

    /**
     * Notifies the drawable that it's displayed state has changed.
     *
     * @param drawable
     * @param isDisplayed
     */
    private static void notifyDrawable(Drawable drawable, final boolean isDisplayed) {
        if (drawable instanceof RecyclingBitmapDrawable) {
            // The drawable is a CountingBitmapDrawable, so notify it
            ((RecyclingBitmapDrawable) drawable).setIsDisplayed(isDisplayed);
        } else if (drawable instanceof LayerDrawable) {
            // The drawable is a LayerDrawable, so recurse on each layer
            LayerDrawable layerDrawable = (LayerDrawable) drawable;
            for (int i = 0, z = layerDrawable.getNumberOfLayers(); i < z; i++) {
                notifyDrawable(layerDrawable.getDrawable(i), isDisplayed);
            }
        }
    }

}
/**
 * A BitmapDrawable that keeps track of whether it is being displayed or cached.
 * When the drawable is no longer being displayed or cached,
 * {@link android.graphics.Bitmap#recycle() recycle()} will be called on this drawable's bitmap.
 */
public class RecyclingBitmapDrawable extends BitmapDrawable {

    static final String TAG = "CountingBitmapDrawable";

    private int mCacheRefCount = 0;
    private int mDisplayRefCount = 0;

    private boolean mHasBeenDisplayed;

    public RecyclingBitmapDrawable(Resources res, Bitmap bitmap) {
        super(res, bitmap);
    }

    /**
     * Notify the drawable that the displayed state has changed. Internally a
     * count is kept so that the drawable knows when it is no longer being
     * displayed.
     *
     * @param isDisplayed - Whether the drawable is being displayed or not
     */
    public void setIsDisplayed(boolean isDisplayed) {
        //BEGIN_INCLUDE(set_is_displayed)
        synchronized (this) {
            if (isDisplayed) {
                mDisplayRefCount++;
                mHasBeenDisplayed = true;
            } else {
                mDisplayRefCount--;
            }
        }

        // Check to see if recycle() can be called
        checkState();
        //END_INCLUDE(set_is_displayed)
    }

    /**
     * Notify the drawable that the cache state has changed. Internally a count
     * is kept so that the drawable knows when it is no longer being cached.
     *
     * @param isCached - Whether the drawable is being cached or not
     */
    public void setIsCached(boolean isCached) {
        //BEGIN_INCLUDE(set_is_cached)
        synchronized (this) {
            if (isCached) {
                mCacheRefCount++;
            } else {
                mCacheRefCount--;
            }
        }

        // Check to see if recycle() can be called
        checkState();
        //END_INCLUDE(set_is_cached)
    }

    private synchronized void checkState() {
        //BEGIN_INCLUDE(check_state)
        // If the drawable cache and display ref counts = 0, and this drawable
        // has been displayed, then recycle
        if (mCacheRefCount <= 0 && mDisplayRefCount <= 0 && mHasBeenDisplayed
                && hasValidBitmap()) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "No longer being used or cached so recycling. "
                        + toString());
            }

            getBitmap().recycle();
        }
        //END_INCLUDE(check_state)
    }

    private synchronized boolean hasValidBitmap() {
        Bitmap bitmap = getBitmap();
        return bitmap != null && !bitmap.isRecycled();
    }

}

主要是对图片进行了及时的释放处理,希望对遇到此问题的人有帮助。额。 忘记说了,用的话,自己的头像处理View,继承它就行了, 只需要做处理下就行了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 06:04:41

在5.0系统上头像展示背景黑块的问题的相关文章

stm32学习笔记之win8系统下,keil4出现黑块的解决方法

前不久,笔者安装keil4启动会出现黑块,如图所示 当时询问了不少技术群都没有找到解决办法,并且还在百度贴吧发贴,最终都无果而终 这是当时发贴地址 http://tieba.baidu.com/p/3176578044 后来重做了个系统,才勉强能使用.直至今天又出现了同样的状况.在此之间笔者发现当keil4出现黑块,win8自带的记事本也会出现未响应状况,于是上网找解决方法,最终网友 oafaq给了我思路 这是他的原文地址 http://blog.sina.com.cn/key9928 .原来我

Android开发之深入理解Android 7.0系统权限更改相关文档

摘要: Android 6.0之后的版本增加了运行时权限,应用程序在执行每个需要系统权限的功能时,需要添加权限请求代码(默认权限禁止),否则应用程序无法响应:Android 7.0在Android 6.0的基础上,对系统权限进一步更改,这次的权限更改包括三个方面: APP应用程序的私有文件不再向使用者放宽 Intent组件传递file://URI的方式可能给接收器留下无法访问的路径,触发FileUriExposedException异常,推荐使用FileProvider DownloadMana

【亲测】appium_v1.4.16版本自动化适配android7.0系统

要解决的问题:appium在androidV7.0系统上运行时报错 Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install io.appium.settings without first uninstalling.] 原因分析:appium的uiautomator版本与androidV7.0不适配. 预置条件:手机端已经安装完Appium Settings 和 Unlock两个应用 解决步骤:1.修改源码文件-注释安装appi

在 Linux 系统上源码安装 GTK+ 2.0

在 Linux 系统上源码安装 GTK+ 2.0==================================================Keywords: GTK+, Install, Linux, SourceAuthor:       whyglinux (whyglinux AT hotmail DOT com)Date:          2007-01-07==================================================目录0. 前言1.

Android6.0机型上调用系统相机拍照返回的resultCode值始终等于0的问题

版权声明:本文为博主原创文章,未经博主允许不得转载. 正常情况下调用系统相机拍照: 如果拍照后点击的是“确定”图标,返回的resultCode = -1(Activity.RESULT_OK): 如果点击的是底部的“返回”键,返回的resultCode = 0(Activity.RESULT_CANCELED). 简单的调用系统相机的写法: //调用系统拍照 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); String p

使用 VirtualBox 虚拟机在电脑上运行 Android 4.0 系统,让电脑瞬间变安卓平板

Ref: http://www.iplaysoft.com/android-v4-ics-for-virtualbox.html 随着?Android?手机的各种软件应用越来越多,很多没有购买的朋友都纷纷表示想要试一试.虽然官方的Android SDK开发包中附带有模拟器,但安装使用上较为复杂,不太适合咱们普通青年,于是我们介绍了一款更易用的BlueStacks 安卓模拟器,不过它也还有一些不爽的地方,譬如只能在 Windows 上运行,或是有时不能连接网络. 所以今天给大家介绍另外一款可以在

Android5.0系统的优缺点

Android L(5.0)正式定名为 Lollipop(棒棒糖).安卓已经六岁了,也总算有一次重大改观了.安卓5.0 Lollipop带来了全新的,扁平化的外观,更好的通知中心,重新设计的核心应用,并提升了在安卓设备上的性能表现--增加了一些以前所缺失的重要应用类别. 首先来看一下Android L相比之前的版本有什么新鲜的东西. 原文博客请参考:点击打开链接 一:自定义通知中心 Lollipop为用户带来了对通知中心前所未有的控制性,每一个应用程序都可以在通知中心进行单独的设置,并且只有在用

从0系统学Android--4.1探究碎片

从0系统学Android--4.1探究碎片 本系列文章目录:更多精品文章分类 本系列持续更新中.... 初级阶段内容参考<第一行代码> 第四章:手机平板要兼顾--探究碎片 平板电脑和手机最大的区别就在于屏幕的大小,一般手机的屏幕大小会在 3 英寸到 6 英寸之间,而一般平板电脑屏幕大小会在 7 英寸到 10 英寸之间.屏幕大小差距过大会导致同样的界面视觉效果有很大的差异. 为了兼顾手机和平板开发,Android 3.0 引入了碎片的概念,可以让界面在平板上更好的展示. 4.1 碎片是什么 碎片

机房收费系统上下机之观察者模式的尝试

如果读者想在本篇文章中看到观察者模式的巧妙应用,大概有些不可能了.因为这里我只是想把自己的一种思路展现给大家,然后和大家探讨. 背景: 在敲机房收费系统的过程中,都是别人说可能会用到什么模式,然后自己针对这些模式进行思考,然后去模仿书中的例子去用. 这不,师姐说上下机这里能用观察者模式,然后我就琢磨了一番,只是收获不是很丰硕,貌似也和师姐讲课中的设想不一样. 我在琢磨使用观察者模式时,已经把系统中和上下机有关的功能实现了.只是在写代码的过程中发现,每次下机,都需要先把正在上机的卡的上机信息查出来