Android Bitmap 计算内存

01.如何计算占用内存

  • 如果图片要显示下Android设备上,ImageView最终是要加载Bitmap对象的,就要考虑单个Bitmap对象的内存占用了,如何计算一张图片的加载到内存的占用呢?其实就是所有像素的内存占用总和:
  • bitmap内存大小 = 图片长度 x 图片宽度 x 单位像素占用的字节数
  • 起决定因素就是最后那个参数了,Bitmap’常见有2种编码方式:ARGB_8888和RGB_565,ARGB_8888每个像素点4个byte,RGB_565是2个byte,一般都采用ARGB_8888这种。那么常见的1080*1920的图片内存占用就是:1920 x 1080 x 4 = 7.9M
阅读更多

Android 加载图片资源介绍

01.加载Bitmap

1.1 什么是bitmap

  • 位图文件(Bitmap),扩展名可以是.bmp或者.dib。位图是Windows标准格式图形文件,它将图像定义为由点(像素)组成,每个点可以由多种色彩表示,包括2、4、8、16、24和32位色彩。位图文件是非压缩格式的,需要占用较大存储空间。
阅读更多

Android 图片相关整理

01.网络请求图片资源

1.1 直接通过http请求网络图片通过流转化成Bitmap

  • 经过测试,请求8张图片,耗时毫秒值174。如果是服务器响应速度一般,耗时需要2秒【正式接口】。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    /**
    * 请求网络图片转化成bitmap
    * @param url url
    * @return 将url图片转化成bitmap对象
    */
    private static long time = 0;
    public static Bitmap returnBitMap(String url) {
    long l1 = System.currentTimeMillis();
    URL myFileUrl = null;
    Bitmap bitmap = null;
    HttpURLConnection conn = null;
    InputStream is = null;
    try {
    myFileUrl = new URL(url);
    } catch (MalformedURLException e) {
    e.printStackTrace();
    }
    try {
    conn = (HttpURLConnection) myFileUrl.openConnection();
    conn.setConnectTimeout(10000);
    conn.setReadTimeout(5000);
    conn.setDoInput(true);
    conn.connect();
    is = conn.getInputStream();
    bitmap = BitmapFactory.decodeStream(is);
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (is != null) {
    is.close();
    conn.disconnect();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    long l2 = System.currentTimeMillis();
    time = (l2-l1) + time;
    LogUtils.e("毫秒值"+time);
    //保存
    }
    return bitmap;
    }
阅读更多

Android 消息机制 ThreadLocal

01.Android消息机制

  • 说起Android消息机制,老生常谈的问题,Handler,Looper,MessageQueue,Message这几个都是离不开的话题,不同的类承载不同的功能,首先还是简单的总结下各自的功能:
    • Handler:发送和处理消息
    • MessageQueue:消息队列,采用单链表结构存储数据
    • Looper:调用loop()轮询消息
    • Message:需要发送的内容,消息
阅读更多

Android HandlerThread

01.HandlerThread介绍

1.1 HandlerThread定义

  • HandlerThread是个什么东西,是一个hanlder还是thread,还是别猜了,直接看一下类的定义吧,英文看不懂,可以找翻译?

阅读更多

Android 子线程更新 UI

01.Android中子线程可以更新UI吗

  • 出自《Android艺术探索》
  • 这是因为Android的UI控件不是线程安全的,如果在多线程中并发访问可能会导致UI控件处于不可预期的状态,那么为什么系统不对UI控件的访问加上锁机制呢?缺点有两个:
    • ①首先加上锁机制会让UI访问的逻辑变得复杂
    • ②锁机制会降低UI访问的效率,因为锁机制会阻塞某些线程的执行。
    • 所以最简单且高效的方法就是采用单线程模型来处理UI操作。
阅读更多

Android 主线程中 Looper 的轮询死循环为何没阻塞主线程

01.造成ANR的原因

  • 造成ANR的原因一般有两种:
    • 当前的事件没有机会得到处理(即主线程正在处理前一个事件,没有及时的完成或者looper被某种原因阻塞住了)
    • 当前的事件正在处理,但没有及时完成
  • 为了避免ANR异常,android使用了Handler消息处理机制。让耗时操作在子线程运行。

02.问题描述

阅读更多

Android MessageQueue

01.MessageQueue作用介绍

  • MessageQueue,主要包含2个操作:插入和读取。
    • 读取操作会伴随着删除操作,插入和读取对应的方法分别为enqueueMessage和next,其中enqueueMessage的作用是往消息队列中插入一条消息,而next的作用是从消息队列中取出一条消息并将其从消息队列中移除。
  • 虽然MessageQueue叫消息队列,但是它的内部实现并不是用的队列。
阅读更多

Android Looper 深度解析

01.Activity如何自动绑定Looper

  • 主线程如何自动调用Looper.prepare()

  • ActivityThread,并且在main方法中我们会看到主线程也是通过Looper方式来维持一个消息循环。那么这个死循环会不会导致应用卡死,即使不会的话,它会慢慢的消耗越来越多的资源吗?

    • 对于线程即是一段可执行的代码,当可执行代码执行完成后,线程生命周期便该终止了,线程退出。而对于主线程,我们是绝不希望会被运行一段时间,自己就退出,那么如何保证能一直存活呢?简单做法就是可执行代码是能一直执行下去的,死循环便能保证不会被退出。
阅读更多

Android Handler 深度解析

01.Handler构造方法

  • 首先看看构造方法

    • 可以看出在Handler的构造方法中,主要初始化了一下变量,并判断Handler对象的初始化不应再内部类,静态类,匿名类中,并且保存了当前线程中的Looper对象。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public Handler(Callback callback, boolean async) {
    if (FIND_POTENTIAL_LEAKS) {
    final Class<? extends Handler> klass = getClass();
    if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
    (klass.getModifiers() & Modifier.STATIC) == 0) {
    Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
    klass.getCanonicalName());
    }
    }

    mLooper = Looper.myLooper();
    if (mLooper == null) {
    throw new RuntimeException(
    "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
    }
阅读更多