Android-开源项目介绍



### 01.课程介绍


> 0.开源项目介绍


> 1.Volley四大请求


> 2.LruCache实现图片缓存


> 3.缓存更新策略:什么时候更新(模块间跳转清空缓存),豌豆荚、京东商城


> 4.自定义Volley请求


> 5.二次封装Volley请求:


> 6.Volley绑定Activity生命周期


> MVP框架


### 02.开源项目介绍


> 以后开发:开发速度,UI和业务的问题
> 以后遇到UI的问题,90%github都可以找到解决方案


> 1.GridView拖拽排序:[https://github.com/fishCoder/DragGridView](https://github.com/fishCoder/DragGridView)


> 2.绘制图表:[https://github.com/HackPlan/AndroidCharts](https://github.com/HackPlan/AndroidCharts)


> 3.视差效果:parallax ,[https://github.com/kanytu/android-parallax-recyclerview](https://github.com/kanytu/android-parallax-recyclerview)


> 带粘性头部、并且排序:[https://github.com/jiyouliang/StickyHeaderListView](https://github.com/jiyouliang/StickyHeaderListView)


> zxing生成和扫描,扫描本地图片二维码:[https://github.com/open-android/Zxing](https://github.com/open-android/Zxing)


> 商城类型首页:淘宝[https://github.com/alibaba/vlayout](https://github.com/alibaba/vlayout)


### 03.Volley简单介绍


> 2013年IO大会推出网络请求框架


> 为了解决一切网络请求:UrlConnection、HttpClient,很简单,企业开发需要封装一层,3000-5000还代码,代码不统一


> 特点:自己处理异步,回调UI;支持图片缓存;支持绑定Activity声明周期


> Volley:齐射并发,并发访问服务器




### 04.Volley2个核心类和三部曲


> 2个核心类:Request请求对象、RequestQueue请求队列


> Volley三部曲:


1.创建请求对象
2.创建请求队列
3.将请求对象添加到队列中




### 05.Volley四大请求-StringRequest


StringRequest:返回字符串




### 06.Volley四大请求-JsonObjectRequest


JsonObjectRequest返回json对象




### 07.Volley四大请求-JsonArrayRequest


JsonArrayRequest返回json数组对象


 
### 08.Volley四大请求-ImageRequest








返回Bitmap对象

### 09.Volley四大请求-ImageRequest大图压缩


//图片采样率:图片分辨率是原来的 width/8 * height/8 = 原来的1/8²
 decodeOptions.inSampleSize = 8;


google Volley计算采样率


  static int findBestSampleSize(
            int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) {
        double wr = (double) actualWidth / desiredWidth;
        double hr = (double) actualHeight / desiredHeight;
        double ratio = Math.min(wr, hr);
        float n = 1.0f;
        while ((n * 2) <= ratio) {
            n *= 2;
        }


        return (int) n;
    }


//true:加载到内存,false:先计算压缩比率,先获取宽度,先不加载到内存
decodeOptions.inJustDecodeBounds = false




### 10.Volley四大请求ImageRequest参数Config.RGB




     Bitmap.Config decodeConfig = Bitmap.Config.RGB_565;
      /*
       //计算一张图片大小
       Bitmap.Config.RGB_565:一个像素点16位,一个Byte占8位,2个字节
       Bitmap.Config.ALPHA_8:一个像素点8位,1个字节
       Bitmap.Config.ARGB_4444:一个像素点16位,2个字节
       Bitmap.Config.ARGB_8888:一个像素点32位,4个字节


       有一张图片480 * 800 ,请计算RGB_565图片大小
       一共有480 * 800个像素点,一个像素点占2个字节,总Byte数=480*800*2byte =


       开发中到底使用哪种格式?模糊图片、很小图片,建议使用ARGB_8888;高清大图RGB_565
        Volley中常用RGB_565
        UIL:ARGB_8888


       */




### 11.Volley请求-Map提交参数


//重写方法处理参数
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            Map<String, String> params = new HashMap<String, String>();
            params.put("username", "用户名");
            params.put("password", "密码");
            return params;
        }


### 12.NetworkImageView加载网络图片




   RequestQueue queue = Volley.newRequestQueue(this);
        ImageLoader.ImageCache imageCache = new MyImageCache();
        ImageLoader imageLoader =  new ImageLoader(queue, imageCache);
        mNetImg.setImageUrl(url, imageLoader);



### 13.图片缓存LruCache算法介绍


> 几种引用级别:


* 强引用:我们平时创建的集合(Map、Set、List)当内存不足,不会释放对象
* 软引用:当内存不足,会释放对象。以前缓存图片使用,现在Avoid Soft References for Caching,避免使用软引用缓存,谷歌建议使用LruCache图片缓存

* 弱引用
* 虚引用




> LRU:最近最少使用,当空间不足,移除最近最少使用元素


> 缓存图片:使用集合,集合众多,到底使用哪个?url-bitmap,key-value,只有Map符合key-value

> 算法决定哪个Map,算法LRU,开LruCache文档


new LinkedHashMap<K, V>(0, 0.75f, true);
//initialCapacity :初始化容器大小,和数据库可变长度类似,气球
//loadFactor:负载因子,每次增加比例值
//accessOrder :排序规则,true根据访问顺序排序,false根据插入顺序


> 谷歌使用LinkedHashMap是Map集合,符合key-value形式,并且最后一个参数true,根据访问顺序排序




### 14.LruCache实现图片缓存


private class MyImageCache implements ImageLoader.ImageCache{


        private static final int MAX_SIZE = 5 * 1024 * 1024;//最大缓存5M
        //创建LruCache
        LruCache<String, Bitmap> lruCache = new LruCache<String, Bitmap>(MAX_SIZE){
            //计算每张图片大小
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getByteCount();//注意:单位要统一
            }
        };


        //从缓存读取
        @Override
        public Bitmap getBitmap(String url) {
            return lruCache.get(url);
        }


        //存储到缓存
        @Override
        public void putBitmap(String url, Bitmap bitmap) {
            lruCache.put(url, bitmap);
        }
    }


> 三级存储:网络、本地、内存




### 15.哪些公司使用Volley做图片缓存


> 京东商城


> 豌豆荚




### 16.缓存更新策略


> 什么时候更新缓存:参考京东商城


* 最优方式:模块间跳转清空缓存,下次进来从网络获取。举例子,京东商城手机列表,退出手机列表重新进入,如果没有网络,不显示缓存。本模块才使用缓存,退出模块清空


* 根据时间更新:30分钟,很少使用,开发很麻烦,首页退出不清空缓存


* ListView显示巧克力数据,当服务器修改商品价格,客户端要不要修改?在价格修改前,页面加载完成,不要修改。




### 17.自定义Volley请求


> 请求返回的Bean对象


> 发现StringRequst继承Request<String>,我们继承Request<T>






public class MyRequest<T> extends Request<T> {


    private final Class<T> clazz;
    //成功回调接口
    private final Response.Listener<T> listener;


    public MyRequest(String url, Class<T> clazz, Response.Listener<T> listener, Response.ErrorListener errorListener) {
        super(url, errorListener);
        this.clazz = clazz;
        this.listener = listener;
    }


    //解析服务器返回数据
    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        //参考StringRequest源代码
        T t = null;
        String parsed;
        try {
            //服务器返回字符串
            parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            //String -> Bean:Gson/fastJson
            t = JSON.parseObject(parsed, clazz);


        } catch (UnsupportedEncodingException e) {
            parsed = new String(response.data);
        }
        return Response.success(t, HttpHeaderParser.parseCacheHeaders(response));
    }


    //传递数据给UI
    @Override
    protected void deliverResponse(T t) {
        listener.onResponse(t);
    }
}




### 18.Volley绑定页面声明周期


> 请求对象设置tag


request.setTag(tag);
        request2.setTag(tag);
        request3.setTag(tag);


        queue.add(request);
        queue.add(request2);
        queue.add(request3);


> 退出页面取消请求


protected void onDestroy() {
        super.onDestroy();
        //关闭Volley请求
        Log.d("HttpUtils", "onDestroy取消网络请求,tag="+tag);
       HttpUtils.getInstance().cancelAll(tag);
    }




### 19.Volley二次封装-常规方式


> 网络请求属于业务层:独立封装到另外一个类,不能放到Activity


> 网络数据需要回传给UI,通过接口回调




  public void getComputer(final OnNetResponseListener listener){
        //UrlConnection
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    HttpURLConnection conn = (HttpURLConnection) new URL(URL_COMPUTER).openConnection();
                    InputStream is = conn.getInputStream();
                    String result = IoUtils.convertStreamToString(is);
                    is.close();
                    listener.onSuccess(result);
                } catch (Exception e) {
                    e.printStackTrace();
                    listener.onFailed(e);
                }
            }
        }).start();
    }


    /**
     * 网络请求回调接口
     */
    public interface OnNetResponseListener{
        void onSuccess(String result);
        void onFailed(Exception e);
    }


### 20.Volley二次封装完成


> 原则:使用的地方(Activity使用网络请求工具类)不能出现第三方框架包名


> 数据回传使用自己的接口


### 21.AES加密算法封装


> AES:Advanced Encryption Standard,高级数据加密标准(比DES加密复杂度增加)


> AES:对称加密(一个秘钥,有秘钥就可以破解)




public static String encrypt(String input, String password) {
try {
//加密算法3部曲
//1.创建Cipher对象
Cipher cipher = Cipher.getInstance(algorithm);
//秘钥规范:秘钥字符串转成对象
Key key = new SecretKeySpec(password.getBytes(), algorithm);
//2.初始化加密/解密模式
cipher.init(Cipher.ENCRYPT_MODE, key);
//3.加密/解密
byte[] bytes = cipher.doFinal(input.getBytes());
String encrypt = Base64.encode(bytes);
//System.out.println("AES加密="+encrypt);
return encrypt;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

/**
* AES解密
* @param input
* @param password
* @return
*/
public static String decrypt(String input, String password) {
try {
//加密算法3部曲
//1.创建Cipher对象
Cipher cipher = Cipher.getInstance(algorithm);
//秘钥规范:秘钥字符串转成对象
Key key = new SecretKeySpec(password.getBytes(), algorithm);
//2.初始化加密/解密模式
cipher.init(Cipher.DECRYPT_MODE, key);
//3.加密/解密
byte[] bytes = cipher.doFinal(Base64.decode(input));
String encrypt = new String(bytes);
//System.out.println("AES加密="+encrypt);
return encrypt;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}




### 22.MVP框架介绍


![](imgs/mvc_mvp.PNG)


> Model:业务(网络请求、缓存数据),Bean


> View:视图,Activity、Fragment


> Presenter:起到桥梁的作用,相当于经纪人


> MVP出现时为了解耦MVC




#### 23.MVP框架-Model层实现


> 登录需求:登录显示加载进度,登录成功跳转主页;登录失败提示用户


> Model层:业务,登录业务,面向接口编程




public class UserLoginModel implements IUserLoginModel {
    @Override
    public void login(final String username, final String password, final OnLoginListener listener) {
        //访问网络:判断用户名和密码
        new Thread(new Runnable() {
            @Override
            public void run() {


                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if("heima38".equals(username) && "123".equals(password)){
                    //登录成功
                    User user = new User(username, password);
                    listener.loginSuccess(user);
                }else{
                    //登录失败
                    listener.loginFailed();
                }
            }
        }).start();
    }
}




#### 24.MVP框架-View层实现


> View层如何编码?如何判断哪些是View?


* 判断的原则:哪些属于View就是View,2个EidtText、加载进度条,登录结果
* 1.有那些操作:获取用户名、获取密码
* 2.用什么用户交互:显示进度条、隐藏进度条
* 3.结果是什么:成功跳转主页、失败提示用户


> View层是Activity,由Activity实现View层接口




public interface IUserLoginView {
    //1.有那些操作:获取用户名、获取密码
    /**获取用户名*/
    String getUsername();
    /**获取密码*/
    String getPassword();

    //2.有什么用户交互:显示进度条、隐藏进度条
    /**显示进度条*/
    void showProgressDialog();
    /**隐藏进度条*/
    void hideProgressDialog();

    //3.结果是什么:成功跳转主页、失败提示用户
    /**成功跳转主页*/
    void jump2Main(User user);
    /**失败提示用户*/
    void showLoginError();

}



#### 25.MVP框架-Presenter层实现


> presenter如何编码:


* 起到桥梁作用,既然起到桥梁作用,p层肯定持有model和view层对象




public class UserLoginPresenter implements OnLoginListener {
    /**
     * 既然起到桥梁作用,p层肯定持有model和view层对象:成员变量
     * 既然起到桥梁作用,p层应该提供桥梁方法(登录)
     */


    private IUserLoginModel model;
    private IUserLoginView view;


    /**
     * 2个参数构造方法对吗?p层构造方法谁调用,View层调用
     * 如果是2个参数构造方法,说明Activity肯定持有Model对象,不符合MVP架构
     * @param view
     */
    public UserLoginPresenter(IUserLoginView view) {
        this.model = new UserLoginModel();
        this.view = view;
    }


    /**
     * model层和View层通信方法
     */
    public void login(){
        //显示进度条
        view.showProgressDialog();
        //调用登录业务方法:下面这行代码集中体现P层起到桥梁作用
        model.login(view.getUsername(), view.getPassword(), this);
    }


    @Override
    public void loginSuccess(final User user) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                //隐藏进度条
                view.hideProgressDialog();
                //跳转主页
                view.jump2Main(user);


            }
        });
    }


    @Override
    public void loginFailed() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                //隐藏进度条
                view.hideProgressDialog();
                //提示用户
                view.showLoginError();
            }
        });
    }


    private Handler mHandler = new Handler();
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值