上节我们把简单的项目搭起来了,然后把仓库托管到Github上了,经过分析, 我们觉得有必要把下面两点优化下:
1.URL写死 -> 解析接口返回的Json,处理获取图片URL 2.优化图片加载,添加本地加载
本节就来完成上述的第一点!
1)在Develop上开辟功能分支:parse_json

2)抠脚Json解析接口数据
数据来源接口:Gank.io API
数据来源接口:Gank.io API
这里我们用的是接口是:http://gank.io/api/data/福利/{请求个数}/{第几页} 例如:每页显示10个,第一页:http://gank.io/api/data/福利/10/1
先看下服务器返回的Json格式:

PS:格式化Json的是Chrome的插件:JSON_handle
根据这个我们先来编写我们的Bean类:Sister.java:
/**
* 描述:妹子业务Bean
*
* @author coder-pig: 2016/08/06 17:16
*/
public class Sister {
private String _id;
private String createAt;
private String desc;
private String publishedAt;
private String source;
private String type;
private String url;
private boolean used;
private String who;
// 一些get和set方法...
}
接下来我们编写一个用来解析网络数据的类,这个类里要做的事依次是:
- Step 1:通过HttpUrlConnection发起Get请求,然后获得后台返回的数据,此时是流形式的
- Step 2:我们需要写一个流转成字节数组的方法
- Step 3:将字节数组转成字符串后,得到的就是后台的给我们返回的数据了,接着要做的就 是写一个解析这一大串Json的方法了,我们需要获取Json里我们需要的数据,丢到Bean里
- Step 4:返回处理后的集合数据
于是乎我们编写一个网络请求的处理类:SisterApi.java:
/**
* 描述:网络请求处理相关类
*
* @author coder-pig: 2016/08/07 14:28
*/
public class SisterApi {
private static final String TAG = "Network";
private static final String BASE_URL = "http://gank.io/api/data/福利/";
/**
* 查询妹子信息
*/
public ArrayList<Sister> fetchSister(int count, int page) {
String fetchUrl = BASE_URL + count + "/" + page;
ArrayList<Sister> sisters = new ArrayList<>();
try {
URL url = new URL(fetchUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
Log.v(TAG, "Server response:" + code);
if (code == 200) {
InputStream in = conn.getInputStream();
byte[] data = readFromStream(in);
String result = new String(data, "UTF-8");
sisters = parseSister(result);
} else {
Log.e(TAG,"请求失败:" + code);
}
} catch (Exception e) {
e.printStackTrace();
}
return sisters;
}
/**
* 解析返回Json数据的方法
*/
public ArrayList<Sister> parseSister(String content) throws Exception {
ArrayList<Sister> sisters = new ArrayList<>();
JSONObject object = new JSONObject(content);
JSONArray array = object.getJSONArray("results");
for (int i = 0; i < array.length(); i++) {
JSONObject results = (JSONObject) array.get(i);
Sister sister = new Sister();
sister.set_id(results.getString("_id"));
sister.setCreateAt(results.getString("createdAt"));
sister.setDesc(results.getString("desc"));
sister.setPublishedAt(results.getString("publishedAt"));
sister.setSource(results.getString("source"));
sister.setType(results.getString("type"));
sister.setUrl(results.getString("url"));
sister.setUsed(results.getBoolean("used"));
sister.setWho(results.getString("who"));
sisters.add(sister);
}
return sisters;
}
/**
* 读取流中数据的方法
*/
public byte[] readFromStream(InputStream inputStream) throws Exception {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len ;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
inputStream.close();
return outputStream.toByteArray();
}
}
好的,接着我们就去调用这个网络请求类了,我们把调用写在MainActivity.java里 而Android是不允许在主线程做网络操作的这里我们就不直接new Runnable, 直接写一个AsyncTask,在里面进网络操作,还有一些简单的逻辑。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button showBtn;
private Button refreshBtn;
private ImageView showImg;
private ArrayList<Sister> data;
private int curPos = 0; //当前显示的是哪一张
private int page = 1; //当前页数
private PictureLoader loader;
private SisterApi sisterApi;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sisterApi = new SisterApi();
loader = new PictureLoader();
initData();
initUI();
}
private void initData() {
data = new ArrayList<>();
new SisterTask(page).execute();
}
private void initUI() {
showBtn = (Button) findViewById(R.id.btn_show);
refreshBtn = (Button) findViewById(R.id.btn_refresh);
showImg = (ImageView) findViewById(R.id.img_show);
showBtn.setOnClickListener(this);
refreshBtn.setOnClickListener(this);
}
@Override public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_show:
if(data != null && !data.isEmpty()) {
if (curPos > 9) {
curPos = 0;
}
loader.load(showImg, data.get(curPos).getUrl());
curPos++;
}
break;
case R.id.btn_refresh:
page++;
new SisterTask(page).execute();
curPos = 0;
break;
}
}
private class SisterTask extends AsyncTask<Void,Void,ArrayList<Sister>> {
private int page;
public SisterTask(int page) {
this.page = page;
}
@Override
protected ArrayList<Sister> doInBackground(Void... params) {
return sisterApi.fetchSister(10,page);
}
@Override
protected void onPostExecute(ArrayList<Sister> sisters) {
super.onPostExecute(sisters);
data.clear();
data.addAll(sisters);
}
}
}
核心是这些,还有一些小改动,加了个Application的类,调整了一下结构,变成这样的:

依次键入命令提交代码:

提交完到Github上可以看到:

因为没下载Github客户端,所以分支合并就用命令行走一发了: 切到develop分支上,走一波merge parse_json

然后把合并后的develop提交到Github,(因为一个人开发,所以基本不用处理冲突

好的,推完看到github上的develop内容已经发生了变化

那么开辟的这个parse_json分支,现在已经没什么作用了,我们可以用命令删掉这个分支:

当然,这里我们删除的只是本地仓库,Github上还是有这个分支的,再键入命令:

然后到GitHub上面看看:

好的,分支已经被删除了!develop分支上的代码也是最新的代码了!
今天群里的B神和我反馈了下new AsyncTask可能会导致内存溢出的问题, 仔细一想确实有这个可能,时间关系写的时候并没有注意这个,特意开 了个 asyncTask_bug 的分支来修复这个问题,对MainActivity的代码 进行了修改,修改后的代码如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button showBtn;
private Button refreshBtn;
private ImageView showImg;
private ArrayList<Sister> data;
private int curPos = 0; //当前显示的是哪一张
private int page = 1; //当前页数
private PictureLoader loader;
private SisterApi sisterApi;
private SisterTask sisterTask;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sisterApi = new SisterApi();
loader = new PictureLoader();
initData();
initUI();
}
private void initData() {
data = new ArrayList<>();
}
private void initUI() {
showBtn = (Button) findViewById(R.id.btn_show);
refreshBtn = (Button) findViewById(R.id.btn_refresh);
showImg = (ImageView) findViewById(R.id.img_show);
showBtn.setOnClickListener(this);
refreshBtn.setOnClickListener(this);
}
@Override public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_show:
if(data != null && !data.isEmpty()) {
if (curPos > 9) {
curPos = 0;
}
loader.load(showImg, data.get(curPos).getUrl());
curPos++;
}
break;
case R.id.btn_refresh:
sisterTask = new SisterTask();
sisterTask.execute();
curPos = 0;
break;
}
}
private class SisterTask extends AsyncTask<Void,Void,ArrayList<Sister>> {
public SisterTask() { }
@Override
protected ArrayList<Sister> doInBackground(Void... params) {
return sisterApi.fetchSister(10,page);
}
@Override
protected void onPostExecute(ArrayList<Sister> sisters) {
super.onPostExecute(sisters);
data.clear();
data.addAll(sisters);
page++;
}
@Override
protected void onCancelled() {
super.onCancelled();
sisterTask = null;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
sisterTask.cancel(true);
}
}
源码下载:DrySister
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD