仿网易新闻APP(六)——优化网络任务(在AS中使用okHttp工具包)

来源:互联网 发布:qq for mac 怎么解压 编辑:程序博客网 时间:2024/06/06 09:55

开头讲点题外话,以前的程序员大多数代码都必须自己写,现在本文用到okHttp工具包,这些辅助的开发工具包,是前辈们总结出来的使程序员的编程效率得到了很大的提高,这也就造就了现在的程序员很多就是“傻瓜式编程”。也就是本文需要讲到的,按照以前,如果需要网络请求需要写到诸如输入流与输出流等一大堆代码,现在一句话就可以解决了。


那么程序员的工作大部分就被简化了,计算机软件之所以需要程序员编写代码是因为程序员是链接自然世界(也就是自然语言与计算机之间的桥梁,比如面向对象是程序员将自然世界的实体类化),一旦工作被智能计算机替代,那么也就不需要程序员,想想看,我们是不是要有那么一点危机意识。


如果你想做技术久一点,就有必要学习学习算法及代码优化方面的知识。我们一般看到关于黑客的电影都会投去羡慕的眼光,但是对于应用程序员而言,似乎与其无关,就算想做黑客也力不从心,这是因为外面三到六个月培训出来的人基本连计算机操作系统与系统结构都没学过,这样的程序员你要找漏洞,从何找起?安全方面的程序员在应用级程序员消失后也会存在相当长的时间。这也是知识使然。


好了,下面进入正题,怎么优化网络任务。


1.分析网络任务


我们知道何为网络任务?就是请求网址,返回或上传需要的数据,然而我们前面所写的所有网络的有关任务都是使用的android提供的AsyncTask。


我们一般在AsyncTask中的doInBackground进行网络任务,在AsyncTask中onPostExecute方法里面进行UI操作。但是对于现在网络任务的扩展性,其AsyncTask效率和其功能就出现的局限性。当现在我要做下载的网络请求的时候,我需要重写下载相关的操作。当我需要上传的时候,又需要重新写上传的代码。我相信这些代码难不到你,可是重复应对不同要求而创建的AsyncTask就会在代码中变得密密麻麻,不仅影响代码的美观,还浪费程序员宝贵的时间做些徒劳重复的工作。


那么怎么让代码简洁,功能又多样化,而且又节约时间呢?答案就是我们的OkHttp工具。


2.导入开发包


现在在程序员幸福的很,Android Studio提供了okHttp开发工具的导入方法,下面我们介绍两种导入方式。


①官方包的导入


我们这里只讲解Android Studio的导入方式,因为谷歌在今年底将暂停对eclipse的支持,对于一个淘汰的工具,恐怕不需要过多的讲解了。


在你的项目中打开如下所示的文件:



在该文件中有如下标签dependencies,在其中加入如下两条语句:


dependencies {    compile fileTree(include: ['*.jar'], dir: 'libs')    compile 'com.android.support:appcompat-v7:23.0.1'    compile files('src/libs/jsoup-1.8.3.jar')    compile files('src/libs/BaiduLBS_Android.jar')    compile 'com.squareup.okhttp:okhttp:2.4.0'    compile 'com.squareup.okio:okio:1.5.0'}


最后两条语句就是导入OkHttp开发包,但是由于okHttp内部依赖于okio,所以必须在导入okHttp的同时导入okio。


对于Android Studio的Gradle工具有必要说明一下:


dependencies中

compile files:单文件依赖。

compile fileTree:某个文件夹下面全部依赖。

compile 'com....':远程依赖。应用格式: packageName:artifactId:version


②导入前辈们封装好的okHttp项目


㈠首先,在project下的app目录下新建文件夹projectlibs,如图:



㈡修改settings.gradle文件夹,内容如下:


include ':app:projectLibs:okhttputils'


当然,你可以起自己看起来顺眼的。


㈢在①中build.gradle(Moudle:app)的dependencies中加入如下代码:


compile project(':app:projectLibs:okhttputils')


依赖一个本项目中 名称为 okhttputils 的 model 库。


㈣添加全局插件


当你做完上面的一切,点击Sync now会发现错误指向如下地方:



apply plugin:表示添加插件。


所以还需要在如下文件中添加代码:



在该文件中的dependencies中添加如下代码:


classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0'


这样全局插件就添加成功了。


3.使用OkHttp优化获取天气的代码


我们现在首先使用2中②导入大神封装的OkHttp方式优化请求天气Json数据的方式,具体代码如下所示:


new OkHttpRequest.Builder()        .url(url)        .get(new ResultCallback<String>(){            @Override            public void onError(Request request, Exception e) {            }            @Override            public void onResponse(String response) {                WeatherItem item =WeatherJson.readWeatherFromInputStream(response);                SharedPreferences.Editor editor= PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit();                editor.putString("pm",item.getPm());                editor.putString("current_city", item.getCurrentCity());                editor.putString("current_date",item.getDate());                editor.putString("weather",item.getWeather());                editor.putString("wind",item.getWind());                editor.putString("temperature",item.getTemperature());                editor.commit();            }        });


按行数来说,可能与用AsyncTask差不多,那我们就按“;”号吧,哈哈,就一行而已。


这样写代码即清爽干净,又清晰明了。


下面在看看2中①的方式直接使用官方提供的okHttp工具,得到上面一样效果的代码如下:



//创建okHttpClient对象OkHttpClient mOkHttpClient = new OkHttpClient();//创建一个Requestfinal Request request = new Request.Builder()        .url(url)        .build();//new callCall call = mOkHttpClient.newCall(request);//请求加入调度call.enqueue(new com.squareup.okhttp.Callback() {    @Override    public void onFailure(Request request, IOException e) {    }    @Override    public void onResponse(Response response) throws IOException {        WeatherItem item =WeatherJson.readWeatherFromInputStream(response.body().toString());        SharedPreferences.Editor editor= PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit();        editor.putString("pm",item.getPm());        editor.putString("current_city", item.getCurrentCity());        editor.putString("current_date",item.getDate());        editor.putString("weather",item.getWeather());        editor.putString("wind",item.getWind());        editor.putString("temperature",item.getTemperature());        editor.commit();    }});



这段代码与上面一个明显的不同就是返回的数据处理的多样化,不过,上面经过大神的封装,其也可以实现多样化数据。你只要修改该<>括号的类型,多样性也就不言而喻了。


其实大神就是把上面的代码进行了封装给我们使用,其内部实现是一样的。


很多人可能会问okHttp默认提供了Gson。解析json数据只要提供一个实体类就可以了,用不着像前面那样的麻烦。但是仔细看看百度提供的天气数据,其获取的不仅是今天的天气数据,还有未来几天,与一些描述性的文字。


因为我们不是开发天气APP,我们只需要获取今天的天气有用的信息就可以了,这就导致5%的数据得到了应用,95%的数据浪费掉了,这样在使用Gson去解析就使得效率低下,且耗时。那么在这种情况下,我们使用android studio提供的json解析方法就可以满足应用了。


4.关于okHttp与AsyncTask的区别(也就是okHttp与HttpURLConnection的区别)


为什么只说了HttpURLConnection而没有说HttpClient,因为谷歌把HttpClient舍弃了。所以默认网络请求全为HttpURLConnection。


①网页编码的区别:


okHttp:其从网页获取的String字符串,并不需要注意编码格式,网易每个新闻详情页面都有手机端格式(UTF-8编码格式),而新闻列表页面,除非你输入的手机网页,否则获取的就是电脑端的网页(GBK编码格式),其内部进行的处理,所以你不必担心会获取到乱码的网页信息。


HttpURLConnection:其获取的网页信息字符串的时候,默认不会考虑编码格式问题,其内部不会帮你转换,必须自己手动转换,不然乱码会是一个困扰你的问题。


②网页的多样性


现在的网页多样性是因为(不同的设备会重定向不同的网页以适应不同的需求)


okHttp:你输入的是什么网页,就获取什么网页,不会重定向到任何网页上,也就没有手机网页与电脑网页的区别,那么爬虫程序就会变得一致性。


HttpURLConnection:与你输入的网页无关,显然在Android APP中使用HttpURLConnection获取网页,如果这个网页有手机端显示格式,默认重定向到手机端,而你在不思索的情况下,以为获取的是电脑端的网页,按电脑端的网页格式使用Jsoup解析网页,会发现怎么获取都是空。所以okHttp获取的网页信息具有一致性。


可以看到,我们前面为了展示功能,默认新闻实体类获取的是图片转换成byte[]存储的,这样做无疑会加大内存的消耗,最优的方式是获取图片的网页信息,在adapter异步加载。你也许发现了,你使用网易APP的时候,当网络不好的时候,listView先显示出来的文字,后显示出来的图片。这就是异步加载的结果。


这里之所以不优化网络爬虫程序是因为,仅仅靠okHttp单方面优化网络任务是无法让ListView显示加快的,后面要与优化ListView结合起来,才能解决这个问题。

1 0