zoukankan      html  css  js  c++  java
  • 【Android】《App研发录》总结

    说明

    看这本书的时候,总感觉怪怪的。

    因为在地铁上看完的,作者书中基本都是他自己工作中遇到的问题和坑,虽说这样会让人感觉找到了解决方案,可以再进行深入的研究,可是某些地方介绍的有点片面,仅仅是引用部分博客就以偏概全了。还有可能是涉及的内容大部分都是我自己已经踩过的坑,所以觉得学到的东西不太多。

    再说说值得一看的地方吧,首先也如前面提到的,书中内容基本都是作者工作之谈,所以有很实用的内容,推荐阅读章节:

    App竞品技术分析

    个人认为这是本书的精华,很少看到有人愿意这样详尽的介绍自己的“机密”经验,感谢作者的无私分享。

    五、六、七章的异常和ProGuard

    介绍很详细,网上都是非常琐碎的介绍,推荐新人看看这部分,尤其是ProGuard,虽然现在第三方已经给出了完善的解决方案,帮我们做了这部分事情,不过了解最基本的原理才能学得更透彻。

    项目、团队管理部分

    这部分是时间的积累才能收获的,提前学习了解以后我们必须经历的路没什么不好的。测试部分相关的部分是很少有书籍能够提及,值得看看。

    第一章小结

    重构目录

    将混乱类文件按照自己的职责划分并存放在相关目录下,如:

    com.xxx.xxx. | -- activity
    			| -- utils
      			| -- adapter
      			| -- entity
      			| -- ui
      			| -- interface
      			| -- listener
    

    有了清晰的目录结构,寻找各功能的类文件方便得多,而且便于团队间多人协作开发。谁也不愿意找个相关类全路径的到处搜,干这种事的人不被同事骂死才怪。

    归类注意的几个点:

    • 遵循单一职责原则,业务、功能耦合过多的文件、代码尽量拆分为多个文件或方法
    • 形象化,类名、方法名一眼就应该知道干嘛的,取名别太抽象,Activity1.java这种名是欠打呢。与视频相关的Activity应取名:VideoActivity.java,听过有人喜欢把Activity放在前面(ActivityVideo.java)看起来统一,但感觉那样进行索引文件的时候不方便,每次都要打全Activity + Suffix,不如Prefix来得方便。

    重定义生命周期

    该部分主要说明对Activity一个简单的封装,Activity都继承一个基类BaseActivity,其中BaseActivity将常用的操作封装起来当作一种规范,如onCreate() —> initViews() —> loadData() 。事实上现在很多项目都是使用的各种框架库,如ButterKnife、EventBus,Otto等,所以这种较老的方式或许慢慢少了起来,可主要的抽象思想都应该有嘛。

    统一编程模型

    这个地方个人不是太赞同作者推荐的View.setOnClickListener(new OnClickListener() { Override onclick() { … } }这种方式来进行事件注册。确实switch … case … 有点“扰乱”面向对象的风格,可想想一个代码较多的Activity中,你要迅速定位某个onClick事件使用后者有多么方便,并且onClick的事件都能统一管理,无需再担心某个地方漏了一个onClIck。

    实体化编程

    通过固定的类库达到我们想要的目的,常用类库Gson、FastJson等,不用过多赘述。其中有一点值得一看,就是关于后面提到的Crash事件处理,其实在传递Intent的时候也可进行避免某些Crash的操作,如长时间的闲置导致内存回收时将关键的变量给回收了,当前跳转页面的时候是需要那个变量的,而传递变量的同时可以进行检查判断是否为null来减少跳转后的NPE(NullPointerException) Crash。这些都是我个人的经验。

    推荐工具:

    这里书中提到的工具都过时了吧(绝对没有嘲讽的意思,能分享的人都是伟大的)。因为拿来主义的我一般用的都是Android Studio中的插件GsonFormat ,不支持Eclipse!

    关于更多工具,推荐看看我的博文:Android-Classical-OpenSource的工具篇,有我常用的AS的插件和相关工具的介绍。

    第二章小结

    第二章主讲网络框架的经验,涉及到的有对网络底层框架的封装,作者遇到的坑和某些网络类库的使用优化建议等。对于网络请求这类操作,当前衍生的各种相关类库功能十分强大,而且基本都封装好了,在使用方便的同时可不要忽略底层的概念,一门技术要做到:知其然,知其所以然。这样无论遇到什么问题都能有一颗冷静沉着的心去面对和挑战。

    网络底层封装

    家家使用的工具都不同,但常用的也就那么几个:

    Volley

    目前公司项目用的就是这一个,还是我当时建项以来综合对比后挑的一个,那时候的OkHttp还没有现在这样火好不好。所以我们也当然对Volley进行了简单的封装,这里不说文章,先谈谈我对Volley封装的看法吧。

    打开Volley的目录结构,在toolbox中可以看到网络请求类常用的有这么几个

    String

    • StringRequest :常用的文本、字符串都可以使用此方式。这里给出封装的例子:

    接口类RequestCallbackable.java,用于进行请求结果的回调。

    public interface RequestCallbackable<T> { 
        void onSuccess(T model);
        void onFailure(T msg);
    }
    

    封装方法中,由于请求分为Get和Post两种,并且很可能Post会含有Body,因此需要二次封装,下面是基于StringRequest的一个完整封装类

    public class HttpUtils {
        private static final int VOLLEY_REQUEST_TIMEOUT_MS = 20 * 1000;
        private static final int VOLLEY_REQUEST_RETRY_TIMES = 0;
        /**
         * Get请求
         *
         * @param strKVs 这里的strKVs代表Get的参数字段,
         *               如果没有参数或者body则不填,
         *               格式为:
         *               "user[name]", username,
         *               "user[password]", userPassword,
         *               "user[id]", userId
         */
        public static void doVolleyGet(String getUrl,
                                       final RequestCallbackable requestResult,
                                       final String... strKVs) {
            doVolleyRequest(Request.Method.GET, getUrl, requestResult, strKVs);
        }
    
        /**
         * Post请求
         *
         * @param strKVs 这里的strKVs代表Post的参数、body字段,
         *               如果没有参数或者body则不填,
         *               格式为:
         *               "user[name]", username,
         *               "user[password]", userPassword,
         *               "user[id]", userId
         */
        public static void doVolleyPost(String getUrl,
                                        final RequestCallbackable requestResult,
                                        final String... strKVs) {
            doVolleyRequest(Request.Method.POST, getUrl, requestResult, strKVs);
        }
    
        /**
         * RequestManager需要在Application初始化
         * 关于RequestManager的使用详情请自行谷歌
         */
        private static void doVolleyRequest(int requestMethod, String requestUrl,
                                            final RequestCallbackable requestCallbackable,
                                            final String... paramsStrKVs) {
            if (TextUtils.isEmpty(requestUrl)) return;
            // 使用的是StringRequest
            StringRequest requestPost = new StringRequest(requestMethod, requestUrl,
                    new Response.Listener<String>() {
                        @Override
                        public void onResponse(String resultStr) {
                            if (requestCallbackable != null) {
                              requestCallbackable.onSuccess(resultStr);
                            }
                        }
                    }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    if (requestCallbackable != null) {
                      requestCallbackable.onFailure(volleyError);
                    }
                }
            }) {
    
                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    Map<String, String> params = new HashMap<String, String>();
                    params.put("Authentication", "here put your Token");
                    return params;
                }
    
                @Override
                protected Map<String, String> getParams() throws AuthFailureError {
                    HashMap<String, String> map = new HashMap<String, String>();
                    if (paramsStrKVs != null && (paramsStrKVs.length % 2 == 0)) {
                        for (int i = 0; i < paramsStrKVs.length; i += 2) {
                            map.put(paramsStrKVs[i], paramsStrKVs[i + 1]);
                        }
                    }
                    return map;
                }
    
                @Override
                public byte[] getBody() throws AuthFailureError {
                    String httpPostBody = "";
                    if (paramsStrKVs != null && (paramsStrKVs.length % 2 == 0)) {
                        for (int i = 0; i < paramsStrKVs.length; i += 2) {
                            httpPostBody += (i == 0 ? "" : "&") + paramsStrKVs[i] + "=" + paramsStrKVs[i + 1];
                        }
                    }
                    return httpPostBody.getBytes();
                }
            };
            // 设置volley的请求超时时间,重试次数
            requestPost.setRetryPolicy(new DefaultRetryPolicy(VOLLEY_REQUEST_TIMEOUT_MS, VOLLEY_REQUEST_RETRY_TIMES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
            // queueTag 用于调用cancelAll(queueTag)取消加入队列的请求
            requestPost.setTag(RequestManager.getRequestQueue.getQueueTag());
            RequestManager.getRequestQueue().add(requestPost);
        }
    }
    

    使用方式

    HttpUtils.doVolleyGet("your request url",
                new RequestCallbackable() {
                    @Override
                    public void onSuccess(Object model) {
                        // request onSuccess callback
                        // this callback on UI main thread
                    }
    
                    @Override
                    public void onFailure(Object msg) {
                        // request onFailure callback
                        // this callback on UI main thread
                    }
                },
                "user[name]", username,
                "user[password]", userPassword,
                "user[id]", userId);
    }
    

    Iamge

    ImageRequest

    比起上面的StringRequest要简单,封装方式差不多,也就不多说了。ImageRequest的简单使用方式:

      ImageRequest imagerequest = new ImageRequest("your image url",
                      new Response.Listener<Bitmap>() {
                          @Override
                          public void onResponse(Bitmap bitmap) {
                            // callback on UI main thread
                          }
                      },
                      maxWidth, maxHeight,
                      ImageView.ScaleType.CENTER,
                      Bitmap.Config.ARGB_8888,
                      new Response.ErrorListener() {
                          @Override
                          public void onErrorResponse(VolleyError volleyError) {
                            // error callback on UI main thread
                          }
                      });
    

    NetworkImageView

    这可是个重头戏,通过NetworkImageView.setImageUrl()来进行ImageView的图片下载,结合LRU进行图片的二级缓存(内存、磁盘),需要注意的是,Volley的请求方式都是通过RequestQueue这个队列进行网络访问的,也就是说通常全局只需要使用同一个Queue,那么RequestManager的目的就是为了实例化Queue以保证方法对其正常的调用。
    NetworkImageView的使用方式:

    NetworkImageView imageview = null;
    imageview = (ImageView) findViewById(R.id.your_image_view_id);
    imageview.setImageUrl("your image url", ImageCacheManager.getInstance().getImageLoader());
    

    说到这里,慢慢引申出了ImageCacheManager这个神奇的Manager类,实际上ImageCacheManager也是一个封装类,将Volley的ImageLoader包装起来,实现了二级缓存策略。详情见该作者的GitHub

    JSON

    Json请求方式和StringRequest大同小异,只不过回调的对象是JSONObject罢了,不介绍了。相关请求类如下:

    • JsonRequest
    • JsonObjectRequest
    • JsonArrayRequest
  • 相关阅读:
    累计定时中断次数使LED灯闪烁
    累计主循环次数使LED灯闪烁
    树莓派
    树莓派
    树莓派--bcm2835 library (2) 交叉编译BCM2835
    树莓派 -- bcm2835 library (1)
    树莓派
    树莓派
    树莓派
    树莓派-3 启用root
  • 原文地址:https://www.cnblogs.com/raomengyang/p/5745915.html
Copyright © 2011-2022 走看看