[漫漫PM路] 产品经营进击漫谈-上篇

网要是android客户端好要紧之部分。下面从入门级开始介绍下好Android网络要的执行进程。希望能被刚接触Android网络有的爱人有赞助。
本文包含:

前言

于简书第一不好发文~总想方发一样首有思意义之稿子来想从业4年多的话的阅历。但是想了想,还是期待先对活经营这个职务有个整概述,对想如果从这工作的小伙伴等会生一些启迪,再展开主题类的享受,所以通篇文章就哪当活工作受到造就产品力当即无异于主题将贯穿起来地到底进行艺术描述。
当然就为不过是百贱遭遇的一家之言,但本身深信不疑万变不离其宗,很多方法论的中心理念都是相通的,也想各位简书大神啊能挺胆赐教~~碰撞来思想火花!!


  • HTTP请求&响应
  • Get&Post
  • [HttpClient & HttpURLConnection](#HttpClient & HttpURLConnection)
  • 同步&异步
  • HTTP缓存机制
  • Volley&OkHttp
  • Retrofit&RestAPI
  • 网络图片加载优化
  • Fresco&Glide
  • 图管理方案

活是什么?

率先,我想证明的凡活无处无以。互联网软件出品只是多市面活面临之平等开销。众所周知,产品经营的定义首先是快消巨头宝洁提出的,所以PM的定义在不久消界已经存在一定久远了,并无属一个新生职业。只是人情行业之工种相对来说比较低调及信闭塞,产品部门在快消公司一般属于Marketing部门下于基本之机构,外露的消息及知识会比较少。笔者自我已也是快消产品的从业者,年少无知时误打误撞进入了互联网企业办事,一路走来,发现多业PM的做事逻辑与办法都是相通的。如果大家发空子吧,也可以多读书别的行业产品工作之流水线及方式,相信对晋级自己工作是格外有实益的。(如果发生心上人感兴趣可以留言,以后得分享同首快消产品的日常工作)

这就是说回到产品究竟是呀?我对产品之敞亮是出品是化解问题或者满足急需的靶子。只要满足是规格的有形产品,或无形服务我们还得叫做产品。
小到平瓶和,大及均等部车;一不好旅行路线,一个理财保险产品;一个饭馆,一个课程….生活蒙看得见,看不显现底于我们来说都是均等种植产品,满足了我们有同种需求,或缓解了咱啊问题。作为产品经营可以养成产品分析的惯,日常生活中遇感兴趣的靶子好去思想这活包括了什么有(有形和无形的情),产品满足了呀要求,市场高达有怎么样同类型的出品,那您所接触的这活之优劣势在啊,他可能的设计生产流程是怎的。相信掌握了这个技术,提升的不只是活力,也能大大提升生活备受的辨别和抉择能力。即使有同一天未从活,拥有了出品思路做其他事都得事半功倍。(说远了~~)

之所以,其实除了互联网以外,各大行都生产品经理的职,而且当下文提到森力量是相通之,只是最终产品展示形式不同。设计食品,日用品,化妆品,亦或设计软件,硬件,数据挖掘,甚至同场会,一个走还是产品,我们还好采用产品相通之笔触去进行规划,置于具体从事的行,可以随便个人兴趣去开展。(所以笔者还是那个庆幸于事初期起过任何行当之产品更,为末期在筹划软件出品常常为开发了累累思路。)


HTTP请求&响应

既然说打入门级开始即说说Http请求包的组织。
一致坏呼吁虽是通向目标服务器发送一弄错文本。什么样的文书?有下面结构的文本。
HTTP请求保管结构

请求包

例子:

    POST /meme.php/home/user/login HTTP/1.1
    Host: 114.215.86.90
    Cache-Control: no-cache
    Postman-Token: bd243d6b-da03-902f-0a2c-8e9377f6f6ed
    Content-Type: application/x-www-form-urlencoded

    tel=13637829200&password=123456

央了便会见吸收响应包(如果对面有HTTP服务器)
HTTP响应包结构

响应包

例子:

    HTTP/1.1 200 OK
    Date: Sat, 02 Jan 2016 13:20:55 GMT
    Server: Apache/2.4.6 (CentOS) PHP/5.6.14
    X-Powered-By: PHP/5.6.14
    Content-Length: 78
    Keep-Alive: timeout=5, max=100
    Connection: Keep-Alive
    Content-Type: application/json; charset=utf-8

    {"status":202,"info":"\u6b64\u7528\u6237\u4e0d\u5b58\u5728\uff01","data":null}

Http请求方式有

方法 描述
GET 请求指定url的数据,请求体为空(例如打开网页)。
POST 请求指定url的数据,同时传递参数(在请求体中)。
HEAD 类似于get请求,只不过返回的响应体为空,用于获取响应头。
PUT 从客户端向服务器传送的数据取代指定的文档的内容。
DELETE 请求服务器删除指定的页面。
CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
OPTIONS 允许客户端查看服务器的性能。
TRACE 回显服务器收到的请求,主要用于测试或诊断。

常用只有Post与Get。

产品设计是呀?

那问题来了,何为产品设计?经常看到部分稿子或一些童鞋会不断地会见强调用户体验怎么怎么样,所以页面应该如此设计,上面按钮位置这么张,可是产品之价值实在是因用户交互体验,来规划页面也??

自家道那肯定不是如此,任何时刻,我们必将要于问题或需要的源头去出发,在确定了出品价值,产品定位,设定了而及目标后,再拓展产品的框架,流程,功能,页面的次第设计。不断实践与经项目一起之后,作为产品我们才会以全速判断项目的施行结果,减少试错成本,确保产品之最终之各数据指标与用户举报是向既定需求方向去倒之。

自身当其他行业产品设计简化来说,可以经过以下闭环去完同样软支付还是上线。本篇文章我们第一讨论互联网产品开发闭环,其他行当可以参见是无是暨我产品设计很像。


出品分析

一个活之源于是只要历经数单调研,分析,讨论后才会依据分析结果上产品设计阶段的。那好说产品分析是产品设计的首先步,没有初调研分析过程的产品开发流程是无法预计要担保市场报告的,很可能会见浪费开发资源。该分析好是活0-1底调研分析;或者是产品常规迭代版本中的多寡解析。

那咱们常会面当互联网产品遭言语到BRD,MRD之类的,很多新入行的平纵会以为“哇,专业,是高级产品还是老板做的”,其实并从未这么深。我们每个产品基于自己的任务或需求都得于召开事先仔细地展开以下几独维度的解析,来提升迭代力量。

如上四独维度,每个维度都足以形容过多深度分析的稿子,简书上为出很多,因此本文先简单进行说明,后续还依据实际主题分开进行详细阐述。

市场分析:相似新产品会进展详尽的市场调研,会经公司出品要第三正调研企业进行(一般互联网企业还是产品进行调研)。调研的目的根本是指向针对性市场发只宏观了解,大致的商海用户容量,用户痛点&需求点,行业生态分布,各个公司之商业模式,优劣势等。调研之招:1.
行业报告(起码要找到3只以上部门不同的报),切忌不克因偏概全  2.
如有大量潜在用户,或是市场店内部资料等,可以根据内部资料进行剖析 3.
采取swot分析,波特5力分析等分析法,很多产品的市场分析里都见面出,但自身眷恋强调的不是法本身,而是内容,也尽管是无须吧举行SWOT而召开SWOT分析,停留在理论派,还是如成市场本身及商号具体情况进行务实,可追溯,可尽之辨析。

用户分析:用户与需分析是紧紧相关的。一定是先行分析用户,明确用户人群容量,用户基本属性,用户分类,产出人群画像后,再进一步分析不同用户之需求。To
B和To
C的产品用户分析道尚非绝雷同,本篇文章非详细阐述。用户分析常用手法:1.定性访谈

  1. 定量问卷调研

需要分析: 分析了用户之后,针对不同人群,进行他们的要求挖掘与排序。
需求挖掘与先行级排序可以起以下几个维度进行:1.大频型:需求出现的频率 2.
正需型核心要求:用户基本需求的打,核心要求哪里不吃满足 3.
趋势:技术方向和难度之启幕评估4.
商业价值 :基于前三点综合评估需求价值及预级5.细分叉要求:是不是存在有的细分人群的分割需求不给满足,可以拓展新产品模式挖掘

竞品分析:老重大的一个环,但建议以用户以及需求分析为前提进行。只有真正了解了用户以后才能够对竞品做出科学的论断。很多小卖部见面忽视需求与用户分析,过渡进行竞品分析,然后以互联网一异常抄的模式进行支付。其实,这样的模式则身为在同竞品抢日,很可能打未顶理想的功用。总而言之,我们所有要如由用户出发,了解用户还了解竞品。置于竞品分析细节会再单独开平篇稿子来谈。

数码解析:貌似C端用户产品的迭代版本开发前见面展开多少解析,根据数据的变迁还进行需求挖掘与产品开发调整。数据挖掘和分析为是千篇一律山头死功课,本次先谈论下产品经营常常关注之指标:总用户,新增注册用户,新增下载激活用户,日活跃,月在,日留存,7日有,30日有,使用时长,还有跟各个业务有关的指标(ARPU,
注册购买转化等)


产品设计

大家十分关心到底什么完成一个产品设计。但实则如我们最初已经开了充分调研以及剖析下,一定会形成和谐的粗略的下结论,指引大家进行开发,如果在展开收各项分析后,还无法形成和谐之判断,那说明对业务形式还非极端熟悉,无法形成和谐的判断。建议可寻求大家各自leader的提携。

那么以产品设计阶段,我们必然会经历以下几单级次。

活一定,商业模式,优劣势:立即三碰是产品战略层面的题目,主要出于供销社高层或制品负责人来定,但是当一般产品经营,就算不直接参与设定这些地方,也迟早要是会深入明确自己产品稳定,运作模式,盈利模式,和跟市面达成产品比自己可以劣势在啊,如果无法肯定,可能会见指向之后行事主旋律发生偏差。熟悉程度而达别人一样问,第一时间就会迅速回应出产品一定。那坐产品稳定,商业模式的切实可行探讨,如果大家感谢兴趣呢预留于其后文章展开阐释。

产品核心流程:这点是产品设计过程中那个重大之某些,咱们自然要是杀清晰地因本人产品定位,结合用户用流程,去规划一个成品核心流程,该流程需要会涵盖用户采取流程,同时覆盖有系统很使用流程,使得所有任务可开展下。当然多C端用户产品的成品流程都比较简单,B端由于涉及用户类型多,任务复杂,导致基本流程会比较丰富,所以B,C端设计时之核心也无太一样,简单以用户网购流程也例,让大家探听一下用户用与成品流程中的差别。

习俗消费者行为模式:

冲顾客心理的钻研,消费者作为大致可分成以下转化链(很多书阐述有距离,但是核心转化还是以下几步)

俗电商产品约核心流程(粗略概述):

由此可见见,传统电商产品流程远比用户所感知的转向流程要复杂,原因是用户对于产品采用的回味往往是感性,碎片化的;那产品经营的劳作便只要拿用户的碎片式需求梳理成完全,可实施,可容异常行为的制品流程。在日常工作,生活面临如果加强针对性无序,碎片化的需要或内容进行深度挖掘,提炼成一个可是实施之活流程,且穿梭缠绕产品核心流程打磨产品,使产品成为业界领头羊

至于何以打磨产品核心流程,也得以单独开发一个话题探讨。

活框架:出品框架是当解析了产品为主流程后,梳理出一个是因为多效益点错联成的制品框架,来罩上文提到的产品核心流程。一般在成品0-1之号,会要详细梳理产品框架,并基于产品为主流程与关联的对象不断举行调整。而一个熟的产品,在固化不改之气象下,只是在框架达成做加减法。那咱们于平常做事及生存被,也足以挖掘各种成品做框架分析,大家可以依据产品可视化的功用框架,来梳理该可能的完好框架,包括该产品设计多少对象,多少平台,多少功能模块,功能模块的意向。

活效果:到头来到了大家一直时挂于嘴边之效果,功能。功能要吗?肯定是第一之,但是是不过要害的也罢?不然,我们于统筹产品效果时,也非得不断考虑功能以及核心流程的关联,对基本流程发生第一影响的效用肯定要小心谨慎去举行改变。在功能设计方面,一定要是基于要求优先级进行产品效果的计划和排期。

此外还有一点TIPS,加减法考量。我非错过讨论很多产品必然要是举行减法减法,因为不同之业务场景,用户场景的流水线不尽相同,在一个很复杂的业务流程中,缺失一些效能会使得出品流程不完全。因此无可知始终去谈产品的减法,“断舍离”的产品设计方式仅是C端用户产品设计的同样种方法,我们最终还是若回归至骨子里工作场景被,选择最契合之功效加减法。每当我们需要新加力量的时候,不妨扪心自问下:“这个效果满足了哟需要?”“这个效应对现有流程有啊震慑?” “这个作用上线后预测的用户反映是怎么的?”

交互&UI设计:

说到底一点假设取的凡互与UI设计。这个工作于每个公司执行人不雷同。大部分中小企业面临产品经理就做了成品互设计之任务。那互相设计其实跟用户使用习惯,前端技术更新,创新之用户体验密不可分,判定一个成品的彼此好坏也罢并未一个专程引人注目的正规,除了数报告和用户举报外,可能就是企业高层与团组织内部的使用体验。所以哪养以及升级换代交互设计之力,以及UI鉴赏能力,最好可怜之同一条捷径就是:多扣,多为此。大抵扣是赖看行之竞品,多看无同行业特别是少数注重互动行业面临之标杆(社交类,工具类制品更看重互动),多询问前方的前端技术。每天积累5-10只新产品的竞相,勤做速记和剖析,相信2-3个月以后就是能够针对互相设计来自己独到的见识。
 多用是指当出现交互方案时,特别是纯前端产品经营,同时多设计几乎栽方案,通过内部还是米用户调研,选择相同种植满意度最高的方案。


种开支

列支付过程中,产品经营扮演的是一个路管理,质量将控的角色。一般我们于成品方案制定好之后,建议以专业评审之前跟基本研发同学先提前非正式地联系一下子要想法和做法,这样既会保证项目之大势,也能吃研发同学心中有数,提前开始准备。这个做法从实践当中看作用或比好的。那档支付之满贯工艺流程大概来说可以分成以下环节。本篇文章会大体描述下这些环节中比根本的几乎单点,以后重新做具体探讨。

这就是说以档次评审等,可能会见进行1-2潮的评审,在首届评审后,研发同学会根据产品提案提出一些想方设法,针对一些势头或需求点产品可能得更重复修改下流程图,demo等文档。那以多边确认评审内容后,产品跟技巧进行一个型排期,确认需求优先级,开发时间,提测时间以及上线时间。基本上排期之后,确认之产品文档会定稿交付。当然,这里讨论的都是绝大多数景象,也会基于本大小不同,有差的流水线还是操作办法,相对来说还是来同一届弹性空间的。

这就是说档入开发从此,产品在跟进开发的还要,也会准备生只本子的迭代。产品开发过程遭到,可能随着开发促进,会小之前从未讨论到的需求点或深流程出现,这时候就待产品经理充分发挥解决问题的能力,做一个神诸葛,兵来将挡,水来土掩。当然,很多柜以产品开发过程中需要吗会见持续更改,那是改变流程将遵循其实情况去追究了。

当测试上线阶段,产品重点是一个出品体验,问题反馈及品质将控的劳作,承担本的成品主流程,异常流程是不是跑通,页面性能是匪是平静,视觉和交互的功能是无是达标可高达线正式,那产品不可能同测试相同将持有的边际都失去测一布满,但是若保的凡产品主流程跑通,达到可达到丝正式,不然产品上线失败或是上新后用户数量掉的决意,毋庸置疑又大多矣同一软变身背锅侠之时。产品达丝就后,我们司空见惯还需要在线上环境更拓展同样糟体会,如果发现有重大题材,及时同研发沟通进行回滚。


用户举报

用户反映是产品一个本子的竣工,也是另一个巡回的起来。在斯过程被,通过气以及定量的计开展用户举报收集,并开展辨析对生个版效果迭代是很重大的。

定量反馈:那通过普通数据解析的定量反馈一定是对准达成一个本子效果最好直接的验证。上了初成效后活注册,日活,留存,停留时长,和业务有关的指标(比如下单,支付等等)这些健康指标是免是出不行要命起伏;新成效的用人口,每天天都增长等等跟初效能一直或间接相关的数目肯定要是细致分析,如果只要发现新职能对正常数量下降来震慑,可能要立即对拖欠功能做隐藏或下线。

意志反馈:B端产品由于用户量小若集中,会越倚重用户的气反馈。B端产品于客户量大之时节,可以先行选择核心客户的灰度发布,如果基本客户因此下来反馈不是专程好,那好直接砍掉或者未达到新成效。但是众多B端产品的急需都出自大客户之莫过于申报,所以这种气象会较少。C端产品之活经理除了看数据外也要是小心客户定性的反映,可以经过运动上前用户,深入访谈,建立用户社交群来询问典型用户之的确需要及指向己产品直接的感想。

当下同一破以内容比较多,主题比较分散,所以多洒洒写的几近而休精,上文也涉及了实际上过多主题且得以拓展有许多内容谈。以后会招来时机跟大家大饱眼福~~还是那句话:放百小云,融会贯通,让咱们一同扑吧!

Get&Post

网络请求被我们常常因此键值对来传参数(少部分api用json来传递,毕竟非是主流)。
经上面的介绍,可以观看虽然Post与Get本意一个凡表单提交一个是请求页面,但精神并没什么区别。下面说说参数在当下2者的职。

  • Get方式
    当url中填入参数:

      http://xxxx.xx.com/xx.php?params1=value1&params2=value2
    

竟然以路由

    http://xxxx.xx.com/xxx/value1/value2/value3

这些就是web服务器框架的从了。

  • Post方式
    参数是经过编码在请求体中的。编码包括x-www-form-urlencoded
    form-data
    x-www-form-urlencoded的编码方式是这么:
    tel=13637829200&password=123456
    form-data的编码方式是如此:
    —-WebKitFormBoundary7MA4YWxkTrZu0gW
    Content-Disposition: form-data; name=”tel”

      13637829200
      ----WebKitFormBoundary7MA4YWxkTrZu0gW
      Content-Disposition: form-data; name="password"
    
      123456
      ----WebKitFormBoundary7MA4YWxkTrZu0gW
    

x-www-form-urlencoded的优越性就可怜肯定了。不过x-www-form-urlencoded只好传键值对,但是form-data好传二进制

以url是是吃要求行中的。
于是Get与Post区别本质就是是参数是位于请求行蒙或放在请求体
本来无论用哪种都能放在请求头饱受。一般在请求头中加大有发送端的常量。

有人说:

  • Get是明文,Post隐藏
    走端不是浏览器,不用https全都是光天化日。
  • Get传递数据上限XXX
    胡说。有限量的凡浏览器被的url长度,不是Http协议,移动端请求无影响。Http服务器部分发生限制的安一下即可。
  • Get中文需要编码
    是真的…要注意。URLEncoder.encode(params, "gbk");

还是建议就此post规范参数传递方式。并没有啊更精彩,只是大家都如此社会又和谐。

面说之是求。下面说响应。
请求是键值对,但返回数据我们常常因此Json。
对此内存中的结构数据,肯定要用多少描述语言将目标序列化成文本,再用Http传递,接收端并由文本还原成结构数据。
对象(服务器)<–>文本(Http传输)<–>对象(移动端) 。

服务器返回的数额大部分且是繁体的构造数据,所以Json最契合。
Json解析库有众多Google的Gson,阿里的FastJson。
Gson的用法看这里。

产一致想预告~

是因为拿产品经理这个功效的概述浓缩在浅一首文章里,文章过长无便宜阅读。因此,这里预告下漫谈下篇的主题:

HttpClient & HttpURLConnection

HttpClient早于抛弃了,谁又好这种问题也惟有经历落后的面试官才会咨询。具体由可以看这里。

脚说说HttpURLConnection的用法。
最好开始接触的即是以此。

    public class NetUtils {
        public static String post(String url, String content) {
            HttpURLConnection conn = null;
            try {
                // 创建一个URL对象
                URL mURL = new URL(url);
                // 调用URL的openConnection()方法,获取HttpURLConnection对象
                conn = (HttpURLConnection) mURL.openConnection();

                conn.setRequestMethod("POST");// 设置请求方法为post
                conn.setReadTimeout(5000);// 设置读取超时为5秒
                conn.setConnectTimeout(10000);// 设置连接网络超时为10秒
                conn.setDoOutput(true);// 设置此方法,允许向服务器输出内容

                // post请求的参数
                String data = content;
                // 获得一个输出流,向服务器写数据,默认情况下,系统不允许向服务器输出内容
                OutputStream out = conn.getOutputStream();// 获得一个输出流,向服务器写数据
                out.write(data.getBytes());
                out.flush();
                out.close();

                int responseCode = conn.getResponseCode();// 调用此方法就不必再使用conn.connect()方法
                if (responseCode == 200) {

                    InputStream is = conn.getInputStream();
                    String response = getStringFromInputStream(is);
                    return response;
                } else {
                    throw new NetworkErrorException("response status is "+responseCode);
                }

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (conn != null) {
                    conn.disconnect();// 关闭连接
                }
            }

            return null;
        }

        public static String get(String url) {
            HttpURLConnection conn = null;
            try {
                // 利用string url构建URL对象
                URL mURL = new URL(url);
                conn = (HttpURLConnection) mURL.openConnection();

                conn.setRequestMethod("GET");
                conn.setReadTimeout(5000);
                conn.setConnectTimeout(10000);

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

                    InputStream is = conn.getInputStream();
                    String response = getStringFromInputStream(is);
                    return response;
                } else {
                    throw new NetworkErrorException("response status is "+responseCode);
                }

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

                if (conn != null) {
                    conn.disconnect();
                }
            }

            return null;
        }

        private static String getStringFromInputStream(InputStream is)
                throws IOException {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            // 模板代码 必须熟练
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
            is.close();
            String state = os.toString();// 把流中的数据转换成字符串,采用的编码是utf-8(模拟器默认编码)
            os.close();
            return state;
        }
    }

在意网络权限!被坑了稍稍坏。

<uses-permission android:name="android.permission.INTERNET"/>

出品基本能力:独立思考,逻辑分析,解决问题,表达能力…等探索与通常能力培养

倘大家来什么想法,或者是怀念只要询问之主题为得以留言,我会选择自己比善于的开展分享。

同步&异步

立2独概念就是吃多线程编程中。
android中默认只发生一个主线程,也受UI线程。因为View绘制只能于此线程内展开。
于是一旦你死了(某些操作而之线程在这里运行了N秒)这个线程,这间View绘制将未克拓展,UI就会卡。所以若竭尽全力避免以UI线程进行耗时操作。
网络要是一个杰出耗时操作。
经过上面的Utils类进行网络要单出一行代码。

NetUtils.get("http://www.baidu.com");//这行代码将执行几百毫秒。

假如你如此勾画

        @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String response = Utils.get("http://www.baidu.com");
    }

就会死。。
就就是手拉手方式。直接耗时操作阻塞线程直到数据接受了毕然后归。Android不同意的。
异步方式:

         //在主线程new的Handler,就会在主线程进行后续处理。
    private Handler handler = new Handler();
    private TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text);
        new Thread(new Runnable() {
            @Override
            public void run() {
                    //从网络获取数据
                final String response = NetUtils.get("http://www.baidu.com");
                    //向Handler发送处理操作
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                            //在UI线程更新UI
                        textView.setText(response);
                    }
                });
            }
        }).start();
    }

于子线程进行耗时操作,完成后经Handler将更新UI的操作发送至主线程执行。这就算为异步。Handler是一个Android线程模型中要之物,与网无关便不说了。关于Handler不了解就优先失Google一下。
关于Handler原理同首对的文章

然而这么描写好丢人。异步通常伴随者他的好基友回调
立是经回调封装的Utils类。

    public class AsynNetUtils {
        public interface Callback{
            void onResponse(String response);
        }

        public static void get(final String url, final Callback callback){
            final Handler handler = new Handler();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    final String response = NetUtils.get(url);
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onResponse(response);
                        }
                    });
                }
            }).start();
        }

        public static void post(final String url, final String content, final Callback callback){
            final Handler handler = new Handler();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    final String response = NetUtils.post(url,content);
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onResponse(response);
                        }
                    });
                }
            }).start();
        }
    }

下一场以方法。

    private TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.webview);
        AsynNetUtils.get("http://www.baidu.com", new AsynNetUtils.Callback() {
            @Override
            public void onResponse(String response) {
                textView.setText(response);
            }
        });

大凡休是雅很多。
哦,一个懵到哭的网要方案成型了。
拙的地方产生好多:

  • 老是都new Thread,new Handler消耗了死
  • 从未有过充分处理体制
  • 尚未缓存机制
  • 并未完善的API(请求头,参数,编码,拦截器等)与调试模式
  • 没有Https

HTTP缓存机制

缓存对于移动端是很主要之是。

  • 减掉请求次数,减多少服务器压力.
  • 当地数据读取速度再快,让页面不会见空白几百毫秒。
  • 在无网的气象下提供数据。

缓存一般由服务器控制(通过某些方式可本地控制缓存,比如向过滤器添加缓存控制信息)。通过当恳求头上加下面几乎单字端:

Request

请求头字段 意义
If-Modified-Since: Sun, 03 Jan 2016 03:47:16 GMT 缓存文件的最后修改时间。
If-None-Match: "3415g77s19tc3:0" 缓存文件的Etag(Hash)值
Cache-Control: no-cache 不使用缓存
Pragma: no-cache 不使用缓存

Response

响应头字段 意义
Cache-Control: public 响应被共有缓存,移动端无用
Cache-Control: private 响应被私有缓存,移动端无用
Cache-Control:no-cache 不缓存
Cache-Control:no-store 不缓存
Cache-Control: max-age=60 60秒之后缓存过期(相对时间)
Date: Sun, 03 Jan 2016 04:07:01 GMT 当前response发送的时间
Expires: Sun, 03 Jan 2016 07:07:01 GMT 缓存过期的时间(绝对时间)
Last-Modified: Sun, 03 Jan 2016 04:07:01 GMT 服务器端文件的最后修改时间
ETag: "3415g77s19tc3:0" 服务器端文件的Etag[Hash]值

标准以时遵循要求或只有含其中一些字段。
客户端要根据这些消息囤积这次请信息。
然后以客户端发起呼吁的早晚要反省缓存。遵循下面步骤:

浏览器缓存机制

只顾服务器返回304意是数量没有改动滚去念缓存信息。
都年轻的自家呢投机写的纱要框架添加到了缓存机制,还沾沾自喜,直到发生一致上自己看看了下面2只东西。(/TДT)/

Volley&OkHttp

Volley&OkHttp应该是现行最常用之网要求库。用法也蛮相像。都是故构造请求参加请求队列的点子管理网络请求。

先说Volley:
Volley可以由此这个库拓展依赖.
Volley在Android 2.3跟以上版本,使用的凡HttpURLConnection,而当Android
2.2暨以下版本,使用的是HttpClient。
Volley的中心用法,网上资料无数,这里推荐郭霖大神的博客
Volley存在一个缓存线程,一个网络请求线程池(默认4单线程)。
Volley这样直接用支付效率会于低,我将自动用Volley时的各种技术封装成了一个库房RequestVolly.
自身以这个库房中将构造请求的章程封装为了函数式调用。维持一个大局的求队列,拓展一些便宜的API。

但还怎么封装Volley在力量拓展性上镇无法同OkHttp相比。
Volley停止了创新,而OkHttp得到了官方的肯定,并以时时刻刻优化。
从而我最终替换为OkHttp

OkHttp用法见这里
老大友善的API与详尽的文档。
立即篇稿子为描绘的生详细了。
OkHttp使用Okio拓展多少传。都是Square家的。
唯独并无是一直用OkHttp。Square公司还发出了一个Retrofit库配合OkHttp战斗力翻倍。

Retrofit&RestAPI

Retrofit宏的简化了网要的操作,它应说光是一个Rest
API管理库,它是一直以OKHttp进行网络要并无影响而针对OkHttp进行部署。毕竟还是Square公司出品。
RestAPI是同样栽软件设计风格。
服务器作为资源存放地。客户端去要GET,PUT,
POST,DELETE资源。并且是管状态的,没有session的介入。
举手投足端和服务器交互最着重之虽是API的统筹。比如就是一个标准的登录接口。

Paste_Image.png

你们应当看之起是接口对应的恳求保管以及应包约是什么样子吧。
告方式,请求参数,响应数据,都死清晰。
行使Retrofit这些API可以直观的体现在代码中。

Paste_Image.png

接下来采用Retrofit提供给您的之接口的实现类
就能够直接进行网络要获得结构数据。

注意Retrofit2.0互相较1.9开展了大气不般配更新。google上绝大多数课都是冲1.9的。这里有个2.0的教程。

课里开展异步请求是应用Call。Retrofit最劲的地方在支持RxJava。就像自己上图被归的是一个Observable。RxJava上亲手难度比大,但就此过就算更为相差不上马了。Retrofit+OkHttp+RxJava配合框架打有成吨的出口,这里不再多说。

网络要学习及此自己觉得都到到了。。

网图片加载优化

对于图片的传导,就如面的记名接口的avatar字段,并无见面直接拿图纸写在返内容里,而是被一个图的地方。需要常又夺加载。

倘您一直用HttpURLConnection去取得一摆设图纸,你办得到,不过尚未优化就光是独BUG不断demo。绝对免可知规范以。
专注网络图片有些特点:

  1. 她永远不见面转换
    一个链接对应之图一般永远不见面更换,所以当第一坏加载了图片时,就应该给永久缓存,以后就是不再网要。

  2. 其非常占内存
    同摆设图小的几十k多的几M高清无码。尺寸也是64*64届2k图。你不能够不怕这么一直显示到UI,甚至无可知一直放大上内存。

  3. 其如果加载很老
    加载一布置图需要几百ms到几m。这之间的UI占各类图功能也是得考虑的。

说说自家于上头提到的RequestVolley里做的图片请处理(没错我做了,这一部分的代码可以去github里看源码)。

三级缓存

网上时不时说三级缓存--服务器,文件,内存。不过自己道服务器无算是一级缓存,那就算是数量源嘛。

  • 外存缓存
    先是内存缓存使用LruCache。LRU是Least Recently Used
    近期最少使用算法,这里确定一个高低,当Map里对象大小总和超此坏时将用效率低于的靶子释放。我以内存大小限制也经过可用内存的1/8.
    内存缓存里读博的数据就是直接返回,读不顶之朝硬盘缓存要数。

  • 硬盘缓存
    硬盘缓存使用DiskLruCache。这个近乎不在API中。得复制利用。
    眼见LRU就清楚了吧。我将硬盘缓存大小设置为100M。

      @Override
      public void putBitmap(String url, Bitmap bitmap) {
          put(url, bitmap);
          //向内存Lru缓存存放数据时,主动放进硬盘缓存里
          try {
              Editor editor = mDiskLruCache.edit(hashKeyForDisk(url));
              bitmap.compress(Bitmap.CompressFormat.JPEG, 100, editor.newOutputStream(0));
              editor.commit();
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
    
      //当内存Lru缓存中没有所需数据时,调用创造。
      @Override
      protected Bitmap create(String url) {
          //获取key
          String key = hashKeyForDisk(url);
          //从硬盘读取数据
          Bitmap bitmap = null;
          try {
              DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
              if(snapShot!=null){
                  bitmap = BitmapFactory.decodeStream(snapShot.getInputStream(0));
              }
          } catch (IOException e) {
              e.printStackTrace();
          }
          return bitmap;
      }
    

DiskLruCache的原理不再说了(我还解决了它在的一个BUG,向Log中长的多寡增删记录时,最后一长达没有出口,导致最后一长长的缓存一直失效。)

  • 硬盘缓存也从不数据就回来空,然后便往服务器请求数据。

眼看就是任何流程。
可自如此的处理方案或者时有发生那么些受制。

  • 图形未经压缩处理直接存储使用
  • 文件操作以主线程
  • 没到的图形处理API

此前也当这么既够用好直到自己遇上下面俩。

Fresco&Glide

勿用想吧亮堂她都召开了杀健全的优化,重复过去轮子的表现十分愚蠢。
Fresco凡是Facebook公司之非官方科技。光看效果介绍就看看非常有力。使用办法官方博客说的够用详细了。
确三级缓存,变换后底BItmap(内存),变换前的初图片(内存),硬盘缓存。
每当内存管理及成功了无限。对于重度图片应用的APP应该是可怜好之。
其一般是直用SimpleDraweeView来替换ImageView,呃~侵入性较强,依赖上她apk包直接杀1M。代码量惊人。

因而自己管理又欣赏Glide,作者是bumptech。这个库房被大的下在google的开源项目遭到,包括2014年google
I/O大会上揭晓的官方app。
这里出详实介绍。直接下ImageView即可,无需初始化,极简的API,丰富的拓展,链式调用都是自家喜爱的。
添加的进行指的哪怕是这个。
除此以外我耶用了Picasso。API与Glide简直一模一样,功能略少,且有一半年未修复的BUG。

图管理方案

况且说图片存储。不要有自己服务器上面,徒增流量压力,还不曾图处理效果。
推荐七牛与阿里云存储(没因此过其他
π__π
)。它们还发甚关键之等同宗图片处理。在图片Url上丰富参数来对图纸展开部分拍卖又传。
于是乎(七牛之拍卖代码)

    public static String getSmallImage(String image){
        if (image==null)return null;
        if (isQiniuAddress(image)) image+="?imageView2/0/w/"+IMAGE_SIZE_SMALL;
        return image;
    }

    public static String getLargeImage(String image){
        if (image==null)return null;
        if (isQiniuAddress(image)) image+="?imageView2/0/w/"+IMAGE_SIZE_LARGE;
        return image;
    }

    public static String getSizeImage(String image,int width){
        if (image==null)return null;
        if (isQiniuAddress(image)) image+="?imageView2/0/w/"+width;
        return image;
    }

既然如此可以加速请求速度,又能压缩流量。再配合Fresco或Glide。完美的图片加载方案。
但这即需要而把具备图片都存放于七牛要阿里云,这样为没错。

图/文件上传也还是行使她第三正存储,它们还发SDK与官文档教你。
然图片一定要是抽了后上传。上传1-2M大之高清照片没意义。

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注