Bitmap源码解析与抛弃google提供的压缩算法


Bitmap源码解析与抛弃google提供的压缩算法

Android程序员如何切合移动互联网的“星辰和荆棘”
http://ddrv.cn/a/213673


Bitmap图片压缩,大图加载防止OOM
https://dandanlove.blog.csdn.net/article/details/105677102


史上最全!押题率90%的 Android 中高级工程师面试复习大纲及真题答案整理(中篇)
https://www.it610.com/article/1344194310530215936.htm

RGB介绍

Bitmap压缩


inSampleSize BitmapFactory.Options

Bitmap局部解码

为了防止加载 Bitmap 的时候造成 OOM 崩溃,我们首选要知道:

一张图片加载到 Bitmap 的时候的占用的是怎么内存计算;
占用内存过高的时候怎么进行图片压缩减小内存占用;

Bitmap OOM RGB介绍 RGB介绍

RGB8位

ALPHA_8–每个像素占1个字节,存储透明度信息,没有颜色信息。

RGB_565–每个像素占2个字节存储颜色信息,R

ARGB_8888 透明度
图片占用内存的计算

图片占用内存的计算
34
Bitmap BitmapFactory.decodeFile

Bitmap 所占内存大小计算方式:图片长度 x 图片宽度 x 一个像素点占用的字节数。
45
decodeByteArray
OutOfMemory()

decodeByteArray

decodeResource   decodeFile

BitmapFactory.Options

inJustDecodeBounds = true

outMimeType
读取位图尺寸和类型

java.lang.OutOfMemory


内存中如果加载一张 500*500 的 png 高清图片.应该是占用多少的内存?
png 图片应该有alpha通道,所以 Bitmap.Config 是 ARGB_8888 。4个8位一种占用32位。
最终答案: 500 * 500 * 4 = 1000000Bytes = 0.95MB


Bitmap.Config = ARGB_8888

0.95MB
像素密度

,Android 系统必须缩放位图,使其在每个屏幕上占据相同的可见空间,从而导致缩放失真,如模糊。


Android使edittext弹出的软键盘位于输入框下面而不是覆盖输入框
https://blog.csdn.net/qq_36982160/article/details/82802152

提供三个方法:

1:在你的activity中的oncreate中setContentView之前写上这个代码

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
1
1
2:在项目的AndroidManifest.xml文件中界面对应的里加入:

android:windowSoftInputMode="stateVisible|adjustResize" //这样会让屏幕整体上移android:windowSoftInputMode="adjustPan" //这样键盘会覆盖屏幕
1
1
3:把顶级的layout替换成ScrollView,或者说在顶级的Layout上面再加一层ScrollView的封装。这样就会把软键盘和输入框一起滚动了,软键盘会一直处于底部。

getWindow.setSoftInputMode  .LayoutParams.SOFT_INPUT_ADJUST_PAN

android:windowSoftInputMode SOFT_INPUT_ADJUST_PAN

23个密度级别提供一个版本

MDPI HDPI  ldpi   mdpi hdpi xhdpi xxhdpi

像素密度
@drawable/xxx时,系统都会根据屏幕的 dpi 选择适当的位图。如果您没有为某个密度提供特定于密度的资源,那么系统会选取下一个最佳匹配项并对其进行缩放以适合屏幕。


实测:1520 x 2688 大小为 334.28KB 图片,屏幕密度为480的手机;

放在 drawable-xxdpi 下加载到 Bitmap 中占用内存为 16343040(1520*2688*4),因为图片不需要进行缩放,所以只需要计算 ARGB_8888 占用的字节数就行;
放在 drawable-mdpi 下加载到 Bitmap 中占用内存为 147087360(1520*3*2688*3*4) ,因为 mdip 到 xxdpi 图片的宽高分别会放大4倍;
nodpi 目录中的资源被视为与密度无关,系统将不会对它们进行缩放。


android 获取ListView的Item中多个Edittext的输入值
https://blog.csdn.net/k571039838k/article/details/92086459


34
1520 x 2688 drawable-mdpi ARGB_888888

因为 mdip 到 xxdpi 图片的宽高分别会放大4倍;


nodpi

Bitmap压缩
压缩原理

其一是下 采样压缩,其二是 质量压缩。 Bitmap

压缩Bitmap磁盘占用空间的大小

CompressFormat.WEBP
压缩Bitmap磁盘占用空间的大小 -写文件
压缩Bitmap占用内存的大小 -运行时
78尺寸的修改其实就是通过修改像素数,放大的过程称之为上采样,缩小的过程称之为下采样。

Bitmap inSampleSize inSampleSize


inSampleSize

您愿意分配用于加载此图片的内存量。//34
位图配置为=ARGB_8888

下面的方法用于计算样本大小值,即基于目标宽度和高度的 2 的幂:


inJustDecodeBounds = true


decodeSampledBitmapFromResource


options.inJustDecodeBounds = true

calculateInSampleSize options,reqWidth,reqHeight

Nearest Neighbour Resampling
45
createScaledBitmap Matrix

双线性采样 Bilinear Resampling

双线性采样   邻近采样算法


BitmapFactory.Options三件套


BitmapFactory.Options

inScaled  inDensity inTargetDensity
        
        BitmapFactory.Options三件套 
        
        inScaled inDensity inTargetDensity
        
        
        加载到堆内存时已经缩放了大小了
        
        inDensity (inTargetDensity)
inTargetDensity:目标图片的显示宽度

drawable-dpi
    
Bitmap局部解码
Bitmap  BitmapRegionDecoder.newInstance encodeRegion


inPreferredConfig = sOptions

encodeRegion    Bitmap.Config.ARGB_8888    


mRegionDecoder.mRegionDecoder.decodeRegion Rect,sOptions


如何看待Android的Jetpack这一系列库?
https://www.zhihu.com/question/302221538/answer/915248040

Lifecycle入坑指南v LiveData/Room/ViewModel这些去年推出的优秀第一方组件,你也应该使用,这些也在JetPack里。
ViewModel、Room等组件早在
Room入坑详解

Activity
 Foundation、Architecture、Behavior和UI。 Behavior和UI。

Foundation、Architecture、Behavior和UI。

Multidex记录一:介绍和使用

45
Security

Data Binding Lifecycles:LiveData


Paging:Room  ViewModel(ViewModel)

WorkManager:()

WorkManager:

即使应用程序退出或设备重新启动,也可以轻松地调度预期将要运行的可延迟异步任务。

LiveData是  Repository

Behavior CameraX:

DownloadManager

Notifications Wear Auto。


Permissions
Preferences    Sharing    Slices

2.4、UI(界面组件):Ani

Animation & Transitions

Palette(23)

allprojects repositories {


}

implementation
android.arch.lifecycle.runtime lifecycle_version

common-java8 compiler

 Architecture 相关组件的使用
 Architecture

 
Android Jetpack架构组件 — Lifecycle入坑指南
https://mp.weixin.qq.com/s/pCljPZEApHTC70dclkKVIw

Lifecycle管理生命周期也是观察者模式,其中主要涉及到以下几个类:
LifecycleObserver、LifecycleOwner、

Lifecycle、LifecycleRegistry、State、Event。

LifecycleObserver、LifecycleOwner、


Lifecycle

Event枚举:

State    Event

 public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY
    }

    State、Event。

DESTROYED  


public enum State {
        DESTROYED,
        INITIALIZED,
        CREATED,
        STARTED,
        RESUMED;
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }
    
onSaveInstance

    States Event
    
    compiler common-java8 reactivestreams
    34
    MyObserver exceeds LifecycleObserver
    
    onResume
    
    OnLifecycleEvent Lifecycle.Event
        
        lifecycle.addObserver MyObserver
    
Observer
 Event44

本文主要是介绍了Lifecycle相关的API以及简单的使用。
在实际项目中还是要结合ViewModel和LiveData来使用。通过ViewModel来获取所需数据,

并通过观察LiveData对象将数据变化反映到视图中。

Lifecycle ViewModel LiveData

ViewModel来获取所需数据,并通过观察LiveData对象将数据变化反映到视图中。


Jetpack架构组件 — LiveData与ViewModel入坑详解
https://mp.weixin.qq.com/s/EbE8JcY3o5ftiDbCal5VzQ

EventBus 

LiveData Activity Fragment
ViewModel

ViewModel将视图和逻辑进行了分离ViewModel


Activity onCreate (onResume)


Scope    onClear

MutableLiveData

postValue

ViewModel UI  LiveData

val secondViewModel = ViewModelProviders.of(this).get(SecondViewModel::class.java)

ViewModelProviders.of this 

.observe.userData(Observer)


这里通过ViewModelProviders来获取ViewModelProvider在通过get方法来获取ViewModel实例。

ViewModelProviders

数据转换


如果我们想对从服务端获取到的数据进行修改可以使用Transformations操作符。分为Map和switchMap两种。switchMap需要返回一个LiveData对象。

Transformations.map


.observe(this,Observer)

Transformations.switchMap

switchMapData.value

MediatorLiveData

多个数据源  -多个observe

MutableLiveData


MediatorLiveData

.addSource

mediatorLiveData.value = info


MutableLiveData


secondViewModel.mediatorLiveData.observe this,Observer

onChanged(23)


postValue onChanged


postValue执行完成后onChanged方法将接受到回调并通知UI更新数据。


上文也34onChanged是监听data1和data2数据变化的

data1.postValue()

postValue执行完成后onChanged方法将接受到回调并通知UI更新数据。


扩展LiveData active 45

activiry_second 

LiveData<BigDecimal>()


onActive方法被调用说明现在有活动着的观察者,所以添加监听以进行数据的更新。onInactive方法被调用说明没有活动的观察者所以要移除监听。

Android Jetpack架构组件 — Room入坑详解
https://mp.weixin.qq.com/s/Az6ckdXhI75j05Q6ZYGh-A


Room

room-runtime

room-compiler kapt annotationProcessor


@Database

RoomDatabase @Dao

@Dao。
public @abstract

Data Access Objects

Get Entity from db


Persist changes back to db


@Entity tableName

PrimaryKey ColumnInfo name = autoGenerate = true

Ignore  ignoredColumns 参数来指定,效果是一样的。 ignoredColumns = true

Entity注解:
Entity

@Target ElementType.TYPE

RetentionPolicy.CLASS

Entity primaryKeys ignoredColumns indices tableName

PrimaryKey注解:

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.CLASS)
public @interface PrimaryKey {

    boolean autoGenerate() default false;
}

ColumnInfo注解:

Target ElementType = FIELD,METHOD

SQLiteTypeAffinity
default


IntDef      BLOB REAL
NOCASE
UNSPECIFIED,BinaryTree

BINARY


Ignore注解:

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR}) 
@Retention(RetentionPolicy.CLASS) 
public @interface Ignore { 
}
Ignore
45
@Insert onConflict  = 
OnConflictStrategy.REPLACE

@Delete

@Update updateUserByUser


@Query("delete  from user where userId = :id ") 
 fun deleteUserById(id:Long)


Query delete        deleteUserById

update user


Database


首先定义一个抽象类继承RoomDatabase类,并添加注解 @Database 来标识:

Database    RoomDatabase

abstract fun

 companion object { 
 
 }

.databaseBuilder

.allowMainThreadQueries

Room.dataBaseBuilder

.allowMainThreadQueries
使用entities来映射相关的实体类,version来指明当前数据库的版本号
.allowMainThreadQueries


AppDatabase.getInstance this.userDao


生成的数据库在data/data/packageName/databases 目录中。


data/data/packageName/databases 目录中。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值