程序的运行流程:
IWeiboActivity接口:
1. init()方法
完成初始化
2, refresh(Objet ...args)方法
完成窗体刷新
Task任务类:
定义程序中的任务
如:登录,发表新微博,获取用户微博,获取用户详细信息等各种任务
int taskId//当前任务的ID
Map params //当前任务的参数
MainService(核心控制类)
1. MainService的主要功能
完成程序调度
接收UI层数据(任务),完成业务逻辑,返回信息,更新UI
在后台运行(继承自Service类)
线程(实现Runnable接口)
不断侦听UI传过来任务消息
2. MainService流程图预览
1. MainService的核心方法个变量
List<Activity> allActivity 保存当前所有Activity,方便切换 List<Task> allTask 把当前任务加到集合中 然后开启线程在Task中遍历任务 去执行任务 public void run() { while (isrun) { Task lastTask = null; synchronized (allTask) {//这里有可能同时有多个任务并发 所以要加锁同步 if (allTask.size() > 0) { lastTask = allTask.get(0); Log.i("yanzheng", "任务ID" + lastTask.getTaskID()); doTask(lastTask); } } // 每隔一秒钟检查是否有任务 try { Thread.sleep(1000); } catch (Exception e) { } }
当接线程发现任务会调用doTask(Task task)方法去执行任务
Message mess = hand.obtainMessage(); mess.what = task.getTaskID();//将当前任务的ID 放到Message中 mess.obj = Object object;//讲当前任务执行的结果放到message中 hand.sendMessage(mess);//发送当前消息 allTask.remove(task);//当前任务执行完毕 把任务从任务集合中remove public void handleMessage(Message msg) 可以接收一个Message对象 (也就是我们doTask中传递的Message) switch (msg.what) { case Task.TASK_GET_USER_HOMETIMEINLINE://任务ID //因为当前HomeActivity实现了IWeiboActivity这个接口,我们得到当前activity的实例,并调用它实现的刷新方法,同时讲参数传递过去,这里就实现了Service中刷新数据的方法了! IWeiboActivity ia = (IWeiboActivity) MainService.getActivityByName("HomeActivity"); ia.refresh(HomeActivity.REFRESH_WEIBO, msg.obj); break;
前言
随机数是人们生活中的必需品,比如说喝酒时的划拳,骰子,国人喜欢的斗地主,麻将,福彩,游戏中那就跟不用说了。所以说随机数的设计是关乎公平性最重要的决定因素。如果说前面提到的事件都可以预测的话,我想没有人会去参与这些事件。
随机数的用途- 数学 (统计计算, 模拟)
- 游戏(随机掉落宝物,爆击概率)
- 安全(随机密码,证书)
- 测试(白盒测试)
- 物理模型 (掷骰子,掷硬币,白噪声。。。)
- 数学模型
数学模型是通过公用的公式:X(n+1) = (a * X(n) + c) % m。对应参数值:
模m, m > 0
系数a, 0 < a < m
增量c, 0 <= c < m
原始值(种子) 0 <= X(0) < m
其中参数c, m, a比较敏感,或者说直接影响了伪随机数产生的质量。
每个厂商对应都有自己的参数,如果对其它厂商的参数比较感兴趣的话可以看这里。随机种子
随机算法都是通用的,程序中遇到不同的问题,需要根据情况来决定提供什么样的随机种子。通过上面的公式我们知道如果提供相同的种子每次产生的随机序列是一样的。所以程序中常用的方法是用当前时间来做随机算法的种子。但是通过当前时间就一定能每次产生的随机数是不一样的吗?
#include <iostream> #include <ctime> int GetRandNum(int min, int max) { srand(time(NULL)); return (min + rand() %(max - min +1)); } int main() { std::cout<<"the num is:"; for(int i = 0; i < 10; ++i) { std::cout<<GetRandNum(0, 10)<<"\t"; } std::cout<<"\n"; }
为什么结果都是一样的呢,这就是前面说的种子一样的话每次产生的随机数是一样的,因为time(NULL) 只能精确到秒,所以在一秒内程序很轻松执行完。遇到这种问题如何解决呢,当然用精度更高的纳秒是一种解决办法,也可以用当前的随机数做为下次随机的种子也是一种好的方式。
常用随机数算法boost库自己提供的随机数发生器:
#include <boost/random/mersenne_twister.hpp> #include <boost/random/uniform_int_distribution.hpp> int main() { boost::random::mt19937 rng; boost::random::uniform_int_distribution<int> index_dis(0, 10); std::cout<<"the num is:"; for(int i =0; i < 10; ++i) { std::cout<<index_dis(rng)<<"\t"; } std::cout<<"\n"; return 0;
}
#include <iostream> #include <ctime> static int seed = time(NULL); int GetRandNum(int min, int max) { srand(seed); seed = rand(); return (min + rand() %(max - min +1)); } int main() { std::cout<<"the num is:"; for(int i = 0; i < 10; ++i) { std::cout<<GetRandNum(1, 10)<<"\t"; } std::cout<<"\n"; }
facebook的随机种子:
#include "folly/Random.h" #include <unistd.h> #include <sys/time.h> namespace folly { uint32_t randomNumberSeed() { struct timeval tv; gettimeofday(&tv, NULL); const uint32_t kPrime1 = 61631; const uint32_t kPrime2 = 64997; const uint32_t kPrime3 = 111857; return kPrime1 * static_cast<uint32_t>(getpid()) + kPrime2 * static_cast<uint32_t>(tv.tv_sec) + kPrime3 * static_cast<uint32_t>(tv.tv_usec); } }随机数生成器效率 通过生成10,000,000随机数来测试效率和随机数的分布。
boost的随机发生器
#include <boost/random/mersenne_twister.hpp> #include <boost/random/discrete_distribution.hpp> #include <iostream> #include <map> #include <ctime> #include <sys/time.h> #define TEST_COUNT 10000000 int main() { boost::mt19937 gen; double probabilities[] ={0.1, 0.12, 0.2, 0.26, 0.32}; boost::random::discrete_distribution<> dist(probabilities); struct timeval tim; gettimeofday(&tim, NULL); std::cout<<"start time:"<<tim.tv_sec<<"the micro sec is:"<<tim.tv_usec<<"\n"; std::map<float, int> statis_map; for(int i = 0; i < TEST_COUNT; ++i) { statis_map[probabilities[dist(gen)]]++; } gettimeofday(&tim, NULL); std::cout<<"end time:"<<tim.tv_sec<<"the micro sec is:"<<tim.tv_usec<<"\n"; for(std::map<float, int>::iterator iter = statis_map.begin(); iter != statis_map.end(); ++iter) { std::cout<<"the per:"<<iter->first<<"\tresult per:"<<(float)iter->second/TEST_COUNT<<"\n"; } return 0; }
结果为:
自制随机发生器
#include <iostream> #include <cmath> #include <ctime> #include <map> #include <sys/time.h> using namespace std; #define TEST_COUNT 10000000 static int s_rand = time(NULL); float RandomFloat() { srand(s_rand); int i = rand(); s_rand = i; return (float)(i%100)/100; } int main() { float per_array[] ={0.1, 0.12, 0.2, 0.26, 0.32}; timeval tim; gettimeofday(&tim, NULL); cout<<"start time:"<<tim.tv_sec<<"the micro sec is:"<<tim.tv_usec<<"\n"; map<float, int> per_map; for(int i = 0; i < TEST_COUNT; ++i) { float frand = RandomFloat(); float min = 0; float max = 1.0f; for(int i =0; i < 5; ++i){ min = max - per_array[i]; if(frand >= min){ per_map[per_array[i]]++; break; } max = min; } } gettimeofday(&tim, NULL); cout<<"end time:"<<tim.tv_sec<<"the micro sec is:"<<tim.tv_usec<<"\n"; map<float, int>::iterator iter = per_map.begin(); for(;iter != per_map.end(); ++iter) { float per_count = (float)iter->second; cout<<"the per:"<<iter->first<<"\tresult per:"<<per_count/TEST_COUNT<<endl; } return 0; }
结果为:
通过分析得知,两个随机发生器的概率分布,基本上和给出的概率非常吻合,运算速度的话,自制的随机发生器比boost几乎快一倍。经常听到很多人不要重新制造轮子,吐槽c++的程序员喜欢自造轮子。确实已经存在的东西没必要再去重写一边,因为那是浪费时间。但是并不代表说不会造轮子,假如都不知道如何造,又如何分辨轮子的好坏,哪些程序岂不要考蒙来写。那写出来的代码质量也是按随机概率分布的。。。。。
有意思的随机程序 boost生成随机密码#include <boost/random/mersenne_twister.hpp> #include <boost/random/uniform_int_distribution.hpp> int main() { std::string chars( "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "1234567890" "!@#$%^&*()" "`~-_=+[{]{\\|;:'\",<.>/? "); boost::random::mt19937 rng; boost::random::uniform_int_distribution<int> index_dist(0, chars.size() - 1); std::cout<<"You pwd is:\t"; for(int i = 0; i < 8; ++i) { std::cout << chars[index_dist(rng)]; } std::cout << std::endl; }
结果:
自制随机发生器生成密码
#include <iostream> #include <string> #include <ctime> using namespace std; static int seed = time(NULL); int RandomRange(int min, int max) { srand(seed); seed = rand(); return (min + (rand())%(max-min)); } char RollChar() { std::string chars( "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "1234567890" "!@#$%^&*()" "`~-_=+[{]{\\|;:'\",<.>/? "); char ch = chars[RandomRange(0, chars.size())]; return ch; } string RollString(int min, int max) { int str_len = RandomRange(min, max); string str(str_len, '0'); for(int i = 0; i < str_len; ++i) { str[i] = RollChar(); } return str; } int main() { int count, min_length, max_length; cout<<"the count you want to:\n"; cin>>count; cout<<"the min, and max username length:\n"; cin>>min_length>>max_length; if(min_length > max_length || min_length < 0) { cout<<"you stupid boy!!!\n"; return 1; } for(int i = 0; i < count; ++i) { cout<<"the user name is:\t"<<RollString(min_length, max_length)<<"\tThe pwd:\t"<<RollString(8,10)<<endl; } return 0; }
结果:
废话不多说,直接上代码,代码里面注释很详细,不过之前一定要使用权限,
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />这两个权限不是必须的,但是为了以防万一,我一般都写上。
<uses-permission android:name="android.permission.INTERNET" />一定要写上,只要需要联网,都需要写上他,我的博客里面有一份权限大全,有兴趣的可以看看,
android上的权限很严格,使用特定功能必须使用特定的权限。其实,要是都写上不知道是什么结果,我也没有试过。哈哈哈
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="mars.com" android:versionCode="1" android:versionName="1.0" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".Weather2Activity" 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>
java文件如下Activity文件
package mars.com; import java.io.BufferedInputStream; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; public class Weather2Activity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button submit = (Button) findViewById(R.id.submit); submit.setOnClickListener(new OnClickListener() { public void onClick(View v) { try { String querystr = "http://www.google.com/ig/api?weather=,,,39905780,116386890"; URL aURL = new URL(querystr.replace(" ", "%20")); // 从SAXParserFactory中获取SAXParser Log.v("querystr", querystr); Log.v("querystr", querystr.replace(" ", "%20")); // 创建一个SAXParserFactory对象 SAXParserFactory spf = SAXParserFactory.newInstance(); // 利用SAXParserFactory对象spf的newSAXParser()方法生成一个SAXParser对象 SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader();// 从SAXParser中得到XMLReader // 创建一个解析xml文件的GoogleWeatherHandler对象gwh GoogleWeatherHandler gwh = new GoogleWeatherHandler(); // 设定XMLReader类的xml处理对象 */ xr.setContentHandler(gwh); // 解析XML文件内容 */ xr.parse(new InputSource(aURL.openStream())); // 下面进行图片的请求 并生成一幅bmp图像 */ URL iconurl = new URL("http://www.google.com" + gwh.getIconURL()); URLConnection conn = iconurl.openConnection(); conn.connect(); // 获得图像的字符流 InputStream is = conn.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is, 8192); ImageView iv = (ImageView) findViewById(R.id.iconofwheather); Bitmap bm = null;// 生成了一张bmp图像 bm = BitmapFactory.decodeStream(bis); bis.close(); is.close();// 关闭流 System.out.println(bm.getHeight()); iv.setImageBitmap(bm); TextView tv1 = (TextView) findViewById(R.id.condition); tv1.append(gwh.getCurrent_condition()); TextView tv2 = (TextView) findViewById(R.id.temperature); tv2.append(gwh.getCurrent_temp().toString() + "摄氏度"); TextView tv3 = (TextView) findViewById(R.id.humidity); tv3.append(gwh.getCurrent_hum().replace("Humidity", "")); System.out.println(tv1.getText().toString()); System.out.println(tv2.getText().toString()); System.out.println(tv3.getText().toString()); } catch (Exception e) { Log.e("error", e.toString()); } } }); } }
工具类java文件如下package mars.com; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class GoogleWeatherHandler extends DefaultHandler { private boolean in_forecast_information = false; private boolean in_current_conditions = false; private boolean in_forecast_conditions = false; private Integer current_temp; private String current_condition; private String current_hum; private String iconURL; private boolean usingSITemperature = false; // false为华氏度,true为摄氏度 public Integer getCurrent_temp() { return current_temp; } public void setCurrent_temp(Integer currentTemp) { current_temp = currentTemp; } public String getCurrent_condition() { return current_condition; } public void setCurrent_condition(String currentCondition) { current_condition = currentCondition; } public String getCurrent_hum() { return current_hum; } public void setCurrent_hum(String currentHum) { current_hum = currentHum; } public String getIconURL() { return iconURL; } public void setIconURL(/blog_article/String iconURL/index.html) { this.iconURL = iconURL; } @Override public void characters(char[] ch, int start, int length) throws SAXException { } @Override public void endDocument() throws SAXException { } @Override public void endElement(String uri, String localName, String qName) throws SAXException { // TODO Auto-generated method stub if (localName.equals("forecast_information")) { this.in_forecast_information = false; } else if (localName.equals("current_conditions")) { this.in_current_conditions = false; } else if (localName.equals("forecast_conditions")) { this.in_forecast_conditions = false; } } @Override public void startDocument() throws SAXException { } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // TODO Auto-generated method stub if (localName.equals("forecast_information")) { this.in_forecast_information = true; } else if (localName.equals("current_conditions")) { this.in_current_conditions = true; } else if (localName.equals("forecast_conditions")) { this.in_forecast_conditions = true; } else { String dataAttribute = attributes.getValue("data"); if (localName.equals("city")) { } else if (localName.equals("postal_code")) { } else if (localName.equals("latitude_e6")) { } else if (localName.equals("longitude_e6")) { } else if (localName.equals("forecast_date")) { } else if (localName.equals("current_date_time")) { } else if (localName.equals("unit_system")) { if (dataAttribute.equals("SI")) this.usingSITemperature = true; } else if (localName.equals("day_of_week")) { if (this.in_current_conditions) { // 可扩展 } else if (this.in_forecast_conditions) { // 可扩展 } } else if (localName.equals("icon")) { if (this.in_current_conditions) { this.setIconURL(/blog_article/dataAttribute/index.html); } else if (this.in_forecast_conditions) { // 可扩展 } } else if (localName.equals("condition")) { if (this.in_current_conditions) { this.setCurrent_condition(dataAttribute); } else if (this.in_forecast_conditions) { // 可扩展 } } else if (localName.equals("temp_f")) { } else if (localName.equals("temp_c")) { this.setCurrent_temp(Integer.parseInt(dataAttribute)); } else if (localName.equals("humidity")) { this.setCurrent_hum(dataAttribute); } else if (localName.equals("wind_condition")) { // 可扩展 } else if (localName.equals("low")) { int temp = Integer.parseInt(dataAttribute); if (this.usingSITemperature) { // 可扩展 } else { // 可扩展 } } else if (localName.equals("high")) { // int temp = Integer.parseInt(dataAttribute); if (this.usingSITemperature) { // 可扩展 } else { // 可扩展 } } } } }main.xml文件如下<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/submit" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="点击" /> <ImageView android:id="@+id/iconofwheather" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello" /> <TextView android:id="@+id/condition" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <TextView android:id="@+id/temperature" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <TextView android:id="@+id/humidity" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout>
以上是全部的代码,有啥不明白的,我们可以探讨一下。我们互相学习,共同进步。过两天会把xmlPull解析,DOM解析等其他三种解析方式贴出来。