第二天 每日一句
来源:互联网 发布:c语言双阶乘 编辑:程序博客网 时间:2024/04/26 04:31
谢谢大家的厚爱。今天是第二天了,第二个小项目,比第一个要复杂一点点。今天的项目呢是要做一个英语学习小软件,就是英语每日一句。由于是小项目,就不用那么复杂,没有自己去做服务器(自己做也可以,这样最好,可以扩展出很多项目。比如,糗事百科,知乎,或再大点的,美团,淘宝等。可是大项目是要团队做的)。在21世纪,作为一名程序员,不应该推崇单兵做战,之前倒是有很多大神,比如求伯君和WPS,但现在的系统都比较庞大,并且用户需求多元化,并且要求开发周期足够短,所以必须要团队合作。闲话少说,既然没有服务器,那资源从哪里来呢,本文选择金山词霸的每日一句。Let’s go.
一、需求分析
功能性需求:每日显示,一句英语,一张图片,还有翻译,和小编的废话
非功能性需求:要求无网络时程序不会死,网络请求时间要10s之内完成
废话:要想做好需求分析要作为用户去和用户沟通。此,仁者见仁,智者见智。
二、概要设计
内容:金山词霸每日一句http://news.iciba.com/dailysentence/detail-1504.html
数据接口:html
显示内容:图片,英语,汉语,小编
三、详细设计
1、html解析
本文采用JSoup(http://jsoup.org/)进行解析
使用JSoup很简单,首先是导入lib然后build path最后使用如下代码(或参考官方api)进行解析
<span style="font-family:SimSun;">Document doc = Jsoup.connect("http://en.wikipedia.org/").get();Elements newsHeadlines = doc.select("#mp-itn b a");</span>
2、异步任务
对于异步任务就是实现一个类继承AsyncTask类。
AsyncTask定义了三个泛型类型:Params Progress Result。
· Params 启动任务执行的输入参数
· Progress 后台任务执行的百分比
· Result 后台执行任务最终返回的结果
AsyncTask 一个异步加载数据最少要重写以下这两个方法:
· doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
· onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回
有必要的话还得重写以下这三个方法,但不是必须的:
· onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
· onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
· onCancelled() 用户调用取消时,要做的操作
使用AsyncTask类,以下是几条必须遵守的准则:
· Task的实例必须在UI thread中创建;
· execute方法必须在UI thread中调用;
· 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
· 该task只能被执行一次,否则多次调用时将会出现异常;
具体实现请看四中的代码
3、网络图片下载
这个比较固定,基本如下函数,先建立http网络连接,获取到InputStream,然后通过Bitmap生成Bitmap,此时可以显示到ImageView上或者保存,这取决于你。
/** * 网络请求图片生成Bitmap * * @param path * @return */private Bitmap getBitmapByUrl(String path) {Bitmap bm = null;URL url;try {url = new URL(path);HttpURLConnection con;con = (HttpURLConnection) url.openConnection();con.setDoInput(true);con.connect();InputStream is = con.getInputStream();bm = BitmapFactory.decodeStream(is);is.close();} catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return bm;}
4、时间间隔计算
所有的时间都是从1979年开始的。Java提供了方法,可以把日期转换成秒数(相对于1979),然后我们可以把两个日期都转换成秒,然后相减,再然后就是把秒转换成天数,一天24个小时,这不用我说了吧。就知道两个日期相差几天了。
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");Date date = null;try {date = df.parse("2015-08-19");} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();}long old = date.getTime();long now = System.currentTimeMillis();long day = (now - old) / 1000 / 60 / 60 / 12;
四、编码测试
AndroidMenifest.xml 对程序进行配置
<?xml version="1.0" encoding="utf-8"?><!-- package的包名是App运行的凭证 --><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.leo.everyday" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="13" android:targetSdkVersion="21" /> <!-- 同样的网络权限 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- theme设置程序主题风格 holo风格 title栏将随着activity最上面颜色的改变而改变 --> <application android:allowBackup="true" android:icon="@drawable/every_day" android:label="@string/app_name" android:theme="@android:style/Theme.Holo.Light.NoActionBar.TranslucentDecor" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
activity_main.xml 布局文件,内容的显示界面
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/main_bg" android:orientation="vertical" android:paddingBottom="20dip" android:paddingLeft="20dip" android:paddingRight="20dip" android:paddingTop="55dip" > <ImageView android:id="@+id/iv_image_main" android:layout_width="match_parent" android:layout_height="wrap_content" android:adjustViewBounds="true" android:scaleType="centerCrop" android:src="@drawable/test" /> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/tv_text_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="EN" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="@android:color/black" android:textStyle="bold" /> <TextView android:id="@+id/tv_translate_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="CN" android:textColor="@android:color/black" android:layout_margin="6dip" /> <TextView android:id="@+id/tv_editor_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="EDITOR" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="@android:color/black" android:textStyle="italic" /> </LinearLayout> </ScrollView></LinearLayout>
MainActivity.java
package com.leo.everyday;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import org.jsoup.Jsoup;import org.jsoup.nodes.Document;import org.jsoup.nodes.Element;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.AsyncTask;import android.os.Bundle;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;/** * @time 2015-09-12 * @author Leo * @describe 程序主Activity 负责网络请求数据得到html然后进行解析 最过显示到相应的控件上 * */public class MainActivity extends Activity {private Context mContext = null;// 自己private static final String TAG = MainActivity.class.getSimpleName();// Log调试时作为标签private static final String MAIN_URL = "http://news.iciba.com/dailysentence/detail-";// 网络URLprivate static final String IMAGE_CLASS = "r_pic";// html中css定义的属性名 此为图片private static final String TEXT_CLASS = "en";// 英文文本private static final String TRANSLATE_CLASS = "cn";// 翻译文本private static final String EDITOR_CLASS = "editor";// 小编private ImageView imageShow = null;// 显示图片private TextView textShow = null, translateShow = null, editorShow = null;// 显示文本内容@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 设置布局文件// 游戏中会通过继承SurfaceView来自定义游戏布局// 会经常使用此方法findViewsByIds();// 根据ids初始化控件task.execute(calculateUrlByTime());// 执行异步任务 从4.0开始google限制不能在主线程中执行网络任务}/** * 取得控件 */private void findViewsByIds() {imageShow = (ImageView) findViewById(R.id.iv_image_main);textShow = (TextView) findViewById(R.id.tv_text_main);translateShow = (TextView) findViewById(R.id.tv_translate_main);editorShow = (TextView) findViewById(R.id.tv_editor_main);}/** * html解析的异步任务 */private AsyncTask<String, Integer, Sentence> task = new AsyncTask<String, Integer, Sentence>() {@Overrideprotected Sentence doInBackground(String... arg0) {// TODO Auto-generated method stubSentence mSentence = null;// bean接收数据try {Document dom = Jsoup.connect(arg0[0]).get();// Jsoup通过网络连接取得html文档Element imageElement = dom.getElementsByClass(IMAGE_CLASS).first();Element textElement = dom.getElementsByClass(TEXT_CLASS).first();Element translateElement = dom.getElementsByClass(TRANSLATE_CLASS).first();Element editorElement = dom.getElementsByClass(EDITOR_CLASS).first();String image = imageElement.getElementsByTag("img").first().attr("src");String text = textElement.getElementsByTag("a").first().text();String translate = translateElement.getElementsByTag("a").first().text();String editor = editorElement.text();mSentence = new Sentence(image, text, translate, editor);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {System.out.println("网络异常");}return mSentence;}@Overrideprotected void onPostExecute(Sentence result) {// TODO Auto-generated method stubsuper.onPostExecute(result);if (result != null) {showInformation(result);} else {toast("内容空,请重试");}}};/** * 弹出提示 * * @param text */private void toast(String text) {Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();}/** * 把内容显示到控件上去 * * @param result */private void showInformation(final Sentence result) {textShow.setText(result.getText());translateShow.setText(result.getTranslate());editorShow.setText(result.getEditor());/** * 偷一回懒 同样用简单异步任务加载图片 */new AsyncTask<String, Integer, Bitmap>() {@Overrideprotected Bitmap doInBackground(String... arg0) {// TODO Auto-generated method stubBitmap bmp = getBitmapByUrl(arg0[0]);return bmp;}@Overrideprotected void onPostExecute(Bitmap result) {// TODO Auto-generated method stubsuper.onPostExecute(result);imageShow.setImageBitmap(result);}}.execute(result.getImage());}/** * 网络请求图片生成Bitmap * * @param path * @return */private Bitmap getBitmapByUrl(String path) {Bitmap bm = null;URL url;try {url = new URL(path);HttpURLConnection con;con = (HttpURLConnection) url.openConnection();con.setDoInput(true);con.connect();InputStream is = con.getInputStream();bm = BitmapFactory.decodeStream(is);is.close();} catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return bm;}/** * 标准阶段1455对应时期为2015-08-19方便计算出以后日期对应的网页连接 比如:2015-08-20对应为1456和1457 */private static final long OLD_NUMBER = 1455;/** * 计算开始 * * @return */private static String calculateUrlByTime() {String url = MAIN_URL + 1 + ".html";SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");Date date = null;try {date = df.parse("2015-08-19");} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();}long old = date.getTime();long now = System.currentTimeMillis();long day = (now - old) / 1000 / 60 / 60 / 12;long number = OLD_NUMBER + day;url = MAIN_URL + number + ".html";return url;}}
Sentence.java
package com.leo.everyday;/** * @time 2015-09-12 * @author Leo * @describe 内容实体内 java bean * */public class Sentence {private String image;private String text;private String translate;private String editor;public Sentence() {}public Sentence(String image, String text, String translate, String editor) {super();this.image = image;this.text = text;this.translate = translate;this.editor = editor;}public String getImage() {return image;}public void setImage(String image) {this.image = image;}public String getText() {return text;}public void setText(String text) {this.text = text;}public String getTranslate() {return translate;}public void setTranslate(String translate) {this.translate = translate;}public String getEditor() {return editor;}public void setEditor(String editor) {this.editor = editor;}}
项目源码:http://download.csdn.net/detail/zhaicaixiansheng/9101147
五、项目总结
做一个项目最重要的不是编码,而是需求分析和测试。需求做不好,做了也白做;测试没做好,做了还是demo。一个项目要发布交互,首先就是稳定性。再一个就是在实际项目中,就算是大神也会遇到自己不会和地方,这就是知识盲点。或者说,等到了大神的阶段,都不屑于写代码记代码了。所以说,对于一个程序员,重要的是编程的思想和学习的能力。编程思想决定你写出的代码的质量,学习能力决定你开发的速度和发展的前景。对于编程思想,没什么好说的,什么《算法大全》《面向对象分析与设计》《数据结构》《设计模式》《软件工程》等等,这些一定要饿补。学到学习能力,每个人有自己的方法。对于IT技术,我的学习方法是,以IOS为例:首先选择一本书,重点看第一章和下面的目录,然后随便翻翻,这是为了对这个新东西有个全面的了解,知道他是什么,要做什么,能做什么,怎么做;然后就是看每张的最开始的容易的地方,这样是为了掌握基础的东西,可以写出helloworld类的程序。然后就是做项目,遇到什么不会的就百度谷歌api文档,进行学习使用;当你这样达到一定水平后,就是总结和看视频了,总结是系统的全面的理解。看视频是为了知道别人怎么做,并查漏补缺。
好了说了那么多废话,希望对您有所帮助。加油!!!
- 第二天 每日一句
- 每日一句(十三)
- 每日一句英语
- 金山词霸每日一句
- 每日一句071023
- 每日一句
- 每日一句英语
- 【每日一句】20090805
- 每日一句
- 每日一句
- 每日一句英语
- 每日一句英语
- 每日一句1
- 每日一句英语
- 每日一句英语
- 每日一句(July)
- 每日一句(August)
- 每日一句(September)
- Genymotion模拟器无法打开解决方法
- php 数值处理
- nyoj 170 网络的可靠性
- HDOJ 2404 Permutation Recovery(好题,学习了)
- R语言:网页抓取之get the data
- 第二天 每日一句
- 离线安装openssl-devel顺序
- Pentest - Mimikatz
- 20150912-maven安装
- 图片的base64编解码
- Spring+Quartz 集群(含提示序列化错误)
- 泛型的剖解
- CPTTRN1 - Character Patterns (Act 1)
- 滑动窗口的最大值