新华BBC笔记五

三级缓存

  • 三级缓存流程分析

    1. 内存缓存 速度快, 优先读取
    2. 本地缓存 速度其次, 内存没有,读本地
    3. 网络缓存 速度最慢, 本地也没有,才访问网络
  • 三级缓存工具类

MyBitmapUtils

/**
 * 自定义图片加载工具类
 * 
 * @author Kevin
 * 
 */
public class MyBitmapUtils {

    private NetCacheUtils mNetCacheUtils;
    private LocalCacheUtils mLocalCacheUtils;
    private MemoryCacheUtils mMemoryCacheUtils;

    public MyBitmapUtils() {
        mMemoryCacheUtils = new MemoryCacheUtils();
        mLocalCacheUtils = new LocalCacheUtils();
        mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils, mMemoryCacheUtils);
    }

    /**
     * 加载图片的核心api
     * 
     * @param ivPic
     *            ImageView对象
     * @param url
     *            图片链接
     */
    public void display(ImageView ivPic, String url) {
        ivPic.setImageResource(R.drawable.pic_item_list_default);

        // 从内存缓存读
        Bitmap bitmap = mMemoryCacheUtils.getBitmapFromMemory(url);
        if (bitmap != null) {// 如果内存存在,就直接设置并返回
            ivPic.setImageBitmap(bitmap);
            System.out.println("从内存读取图片");
            return;
        }

        // 从本地缓存读
        bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
        if (bitmap != null) {// 如果本地文件存在,就直接设置并返回
            ivPic.setImageBitmap(bitmap);
            System.out.println("从本地读取图片");
            mMemoryCacheUtils.putBitmapToMemory(url, bitmap);// 设置内存图片
            return;
        }

        // 从网络缓存下载
        mNetCacheUtils.getBitmapFromNet(ivPic, url);
    }
}
  • 网络缓存

NetCacheUtils

/**
 * 网络缓存工具类
 * 
 * @author Kevin
 * 
 */
public class NetCacheUtils {

    LocalCacheUtils mLocalCacheUtils;
    MemoryCacheUtils mMemoryCacheUtils;

    public NetCacheUtils(LocalCacheUtils localCacheUtils,
            MemoryCacheUtils memoryCacheUtils) {
        mLocalCacheUtils = localCacheUtils;
        mMemoryCacheUtils = memoryCacheUtils;
    }

    public void getBitmapFromNet(ImageView ivPic, String url) {
        BitmapTask task = new BitmapTask();
        task.execute(new Object[] { ivPic, url });
    }

    class BitmapTask extends AsyncTask<Object, Void, Bitmap> {

        private ImageView imageView;
        private String url;

        /**
         * 返回的对象会自动回传到onPostExecute里面
         */
        @Override
        protected Bitmap doInBackground(Object... params) {
            imageView = (ImageView) params[0];
            url = (String) params[1];
            imageView.setTag(url);
            Bitmap bitmap = downloadBitmap(url);
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            // 这里的result就是doInBackground返回回来的对象
            if (result != null) {
                String ivUrl = (String) imageView.getTag();
                if (url.equals(ivUrl)) {// 确保imageview设置的是正确的图片(因为有时候listview有重用机制,多个item会公用一个imageview对象,从而导致图片错乱)
                    imageView.setImageBitmap(result);
                    System.out.println("从网络缓存读取图片");

                    // 向本地保存图片文件
                    mLocalCacheUtils.putBitmapToLocal(url, result);
                    // 向内存保存图片对象
                    mMemoryCacheUtils.putBitmapToMemory(url, result);
                }
            }
        }
    }

    /**
     * 下载图片
     * 
     * @param url
     * @return
     */
    private Bitmap downloadBitmap(String url) {
        HttpURLConnection conn = null;
        try {
            conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setRequestMethod("GET");
            conn.connect();

            int responseCode = conn.getResponseCode();
            if (responseCode == 200) {
                InputStream inputStream = conn.getInputStream();

                //图片压缩
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 2;//表示压缩比例,2表示宽高都压缩为原来的二分之一, 面积为四分之一
                options.inPreferredConfig = Config.RGB_565;//设置bitmap的格式,565可以降低内存占用

                Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
                return bitmap;
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            conn.disconnect();
        }

        return null;
    }
}
  • 本地缓存

LocalCacheUtils

/**
 * 本地缓存工具类
 * 
 * @author Kevin
 * 
 */
public class LocalCacheUtils {

    private static final String LOCAL_PATH = Environment
            .getExternalStorageDirectory().getAbsolutePath() + "/zhbj_cache";

    /**
     * 从本地读取图片
     * 
     * @param url
     * @return
     */
    public Bitmap getBitmapFromLocal(String url) {
        try {
            String fileName = MD5Encoder.encode(url);
            File file = new File(LOCAL_PATH, fileName);

            if (file.exists()) {
                // 图片压缩
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 2;// 表示压缩比例,2表示宽高都压缩为原来的二分之一, 面积为四分之一
                options.inPreferredConfig = Config.RGB_565;// 设置bitmap的格式,565可以降低内存占用

                Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(
                        file), null, options);
                return bitmap;
            } else {
                return null;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 向本地存图片
     * 
     * @param url
     * @param bitmap
     */
    public void putBitmapToLocal(String url, Bitmap bitmap) {
        try {
            String fileName = MD5Encoder.encode(url);
            File file = new File(LOCAL_PATH, fileName);
            File parent = file.getParentFile();

            // 创建父文件夹
            if (!parent.exists()) {
                parent.mkdirs();
            }

            bitmap.compress(CompressFormat.JPEG, 100,
                    new FileOutputStream(file));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
  • 内存缓存

    • 引用级别

      • 强引用 默认引用, 即使内存溢出,也不会回收
      • 软引用 SoftReference, 内存不够时, 会考虑回收
      • 弱引用 WeakReference 内存不够时, 更会考虑回收
      • 虚引用 PhantomReference 内存不够时, 最优先考虑回收!

        //用法举例
        Bitmap bitmap = new Bitmap();
        SoftReference<Bitmap> sBitmap = new SoftReference<Bitmap>(bitmap);
        Bitmap bitmap2 = sBitmap.get();
        
      • 这些避免内存溢出的引用方式在Android 2.3+的版本上已经不再起太大作用, 因为垃圾回收器会频繁回收非强引用的对象, Android官方建议使用LRUCache. 相关链接: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

    • LRUCache

      可以自动控制内存大小, 及时回收不常用的对象, 用法和HashMap类似
      

MemoryCacheUtils

/**
 * 内存缓存工具类
 * 
 * @author Kevin
 * 
 */
public class MemoryCacheUtils {

    // HashMap<String, SoftReference<Bitmap>> mMemoryCache = new HashMap<String,
    // SoftReference<Bitmap>>();
    LruCache<String, Bitmap> mMemoryCache;

    public MemoryCacheUtils() {
        int maxMemory = (int) Runtime.getRuntime().maxMemory();// 当前手机分配给app进程的最大内存,虚拟机默认16M

        System.out.println("maxMemory:" + maxMemory);
        mMemoryCache = new LruCache<String, Bitmap>(maxMemory / 8) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                int size = value.getRowBytes() * value.getHeight();// 返回bitmap占用的内存大小
                System.out.println("sizeof:" + size);
                return size;
            }
        };
    }

    /**
     * 从内存读取图片
     * 
     * @param url
     * @return
     */
    public Bitmap getBitmapFromMemory(String url) {
        // SoftReference<Bitmap> softBitmap = mMemoryCache.get(url);
        // System.out.println("读取内存图片。。。" + softBitmap);
        // if (softBitmap != null) {
        // Bitmap bitmap = softBitmap.get();
        // System.out.println("读取内存图片成功。。。" + bitmap);
        // return bitmap;
        // }

        Bitmap bitmap = mMemoryCache.get(url);
        return bitmap;
    }

    /**
     * 向内存存图片
     * 
     * @param url
     * @param bitmap
     */
    public void putBitmapToMemory(String url, Bitmap bitmap) {
        // System.out.println("设置内存图片。。。");
        // SoftReference<Bitmap> softBitmap = new
        // SoftReference<Bitmap>(bitmap);// 通过软引用对对象包装
        // mMemoryCache.put(url, softBitmap);
        mMemoryCache.put(url, bitmap);
    }
}

屏幕适配

  • 图片适配

    • 开启4种分辨率的模拟器
    • 在drawable的多个目录下放置内容不同但命名相同的图片
    • 运行程序,查看在不同模拟器上的显示效果
    • 常规做法: 美工只做一套1280*720的图片,放置在drawable-xhdpi的目录下, ImageView宽高指定为确定的值, 不包裹屏幕
  • 布局适配

    • 针对特定分辨率,创建layout文件夹: layout-800x480, layout-land(表示横屏)
    • 800x480 和其他分辨率模拟器对比
    • 常规做法: 该方式不到万不得已,一般不用
  • 尺寸(dimens)适配

    • 设备密度:

      float density = getResources().getDisplayMetrics().density;
      
    • dp = px / 设备密度

    • 常规设备密度: 320x240(0.75), 480x320(1), 800x480(1.5), 1280x720(2)

    • 设置dp值, 在不同屏幕上查看显示的比例
    • 创建文件夹values-1280x720, 在dimens.xml中制定尺寸, 适配屏幕
    • 常规做法: 此方法比布局适配更常用. 美工提供像素px值, 我们使用前需要用px除以设备密度,转换成dp后,写在布局文件中

    • 案例分析: 智慧北京新手引导页小圆点处理

  • 权重适配

    android:weightSum="3" //表示总权重数
    常规做法: 当布局有严格比例分配时, 可以使用权重来处理
    
  • 代码适配

    int width = getWindowManager().getDefaultDisplay().getWidth();
    int height = getWindowManager().getDefaultDisplay().getHeight();
    tv1.setLayoutParams(new LayoutParams((int)(width*0.5), (int)(height*0.2)));
    
    常规做法: 如果是自定义的控件, 没有使用xml布局文件时, 可以在代码中动态设置宽高
    
    案例分析: 智慧北京侧边栏宽度处理
    

消息推送

  • 极光推送

    官方地址: https://www.jpush.cn/

    • 创建应用,获取appkey
    • 按照文档流程, 写推送例子程序

      1. 下载sdk
      2. 拷贝sdk中的AndroidManifest.xml文件, 修改相应内容
      3. 自定义MyReceiver
      4. 后台发送消息, 演示效果
      5. 查看高级功能, 在MyReceiver中打印获取的信息及附加信息
      6. 注意: 极光推送后台最多只能创建3个应用, 所以演示前需要确保已存在应用少于3个
    • 下载Demo并演示

    • 推送原理介绍

      • XMPP协议

        一种基于TCP/IP的应用层协议, 专门用于消息推送, 数据格式为xml
        
      • 长连接

        使用socket请求时, 服务端和客户端都不主动关闭输入输出流, 从而实现长连接
        
      • 心跳包

        客户端每隔一段时间(比如1分钟)向服务器发送一段极短的数据,称为心跳包. 服务器收到数据, 就证明客户端还活着, 就会保持连接,向客户端推送消息. 否则断开连接,节省服务器性能. 客户端重连后,服务器将未发送成功的消息重新发出.
        

语音识别

科大讯飞语音云
http://open.voicecloud.cn/

下载SDK, 阅读SDK文档(MSC开发手册), 按照文档,实现如下三个功能

- 语音识别
- 语音识别弹窗
- 语音
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值