您的位置:首页 > 移动开发 > Android开发

实现PHP服务器+Android客户端(Retrofit+RxJava)第四天客户端与服务器通信的实现

2016-06-16 15:01 393 查看
我的上一篇文章已经介绍了retrofit+rxjava的配置(包括缓存),从这一篇开始就开始讲我要实现的这个app网络请求部分的构思,也就是要请求那些数据,数据的类型等等。

我要实现的客户端

看图:









看了界面基本应该能知道要实现的效果了。我这里就分块说好了

“发现”有以下几块

1. 头条

2. 文字

3. 图片

4. 视频

“更多”我暂时还没想好要实现什么效果

首先不登录也能使用发现功能,区别在于“更多”,没有登录的用户在“更多”的功能上应该有所区别。

头条

先不管下拉刷新和上拉加载更多,轮播图的部分也先不说。首先显示这个页面我们就需要先加载一些数据,一次加载多少,数据的格式等是这里需要考虑的。

看效果页面就知道需要加载的数据包括图片(轮播图的图片,每一个item的图片),item中的文字。上面是直接就能看到的,还有我们点击轮播图或者item之后会加载一个网页,也就是说每一个item里还有一个url数据。

数据就三种描述文字、图片、url三种,该如何组合呢?我们都知道图片的传输是比较消耗资源的,像淘宝是有单独的图片服务器的,注意图片也不存储在数据库中,用的好像是文件的方式,就我们自己做一个app的话,就不用这么高的要求,直接用一个服务器就得了,但是不要把图片存到数据库,所以这里我自己服务器这边的做法是这样的,用一个单独的文件夹来存储图片,把图片的路径存在数据库中。

来说说为什么轮播图要单独区分。首先分类清晰,便于扩展,然后加载数据的时候,不可能从同一个表中去加载轮播图的数据和item的数据,如果加载的是同一个表的数据,那就不用搞什么轮播图了都和其他数据的优先级一样的。

做个总结,头条页的数据暂时是这样的:

轮播图

class  SlideViewItem{
long id;
String description; //点击之后跳转去的页面的内容的简单描述
long time;//数据发布时间
String picUrl; //图片地址
String Url;//点击之后跳转地址
}


下面的item

class  HeadlineItem{
long id;
String title;  //item标题
String description; //点击之后跳转去的页面的内容的简单描述
long time;//数据发布时间
String picUrl; //图片地址
String Url;//点击之后跳转地址
}


服务器和客户端通信我记得一开始自己瞎搞的时候,第一个遇到的问题就是这个时间的问题,看了一些网上的文章包括公司做了一些项目后,总的感觉客户端用long类型来表示时间,服务器端将时间保存为bigint还是一个不错的选择,用着也方便,这个long类型的时间表示的是到1970年1月1号0时到现在的毫秒数。

除了时间,还有中文乱码也是新手常遇到的问题,这里只要保证统一编码就行了,比如都用utf-8,创建数据库的时候Character set用utf-8,Collation用utf8_general_ci,再有就是php连接数据库代码如下:

mysql_connect(?,?,?);
mysql_query("set names 'utf8'");
mysql_select_db(?);


就多了mysql_query(“set names ‘utf8’”);这么一句,没有的话插入中文会失败,还有php代码最好也要保存成utf-8格式。

文字

文字页的数据和头条是一模一样的,但是为了后续的扩展性,也单独写了一个类

class  TextItem{
long id;
String title;  //item标题
String description; //点击之后跳转去的页面的内容的简单描述
long time;//数据发布时间
String picUrl; //图片地址
String Url;//点击之后跳转地址
}


图片

图片的话数据就少一些,不知道大家有没有用过instagram(国外的app,现在使用需要翻墙),它的浏览图片就是一个照片墙,图片上也没有文字,你点击图片进去之后才会有一些时间、评论等等的详细信息。我这里也就差不多照着做

class  PicItem{
long id;
String description; //点击之后跳转去的页面的内容的简单描述
String picUrl; //图片地址
String Url;//点击之后跳转地址
}


视频

视频的话要显示标题,以及观看的人数,发布时间等,具体如下:

class  VideoItem{
long id;
String description; //点击之后跳转去的页面的内容的简单描述
long time;          //视频发布的时间
String picUrl;      //图片地址
String Url;         //点击之后跳转地址,也就是视频的地址
int number;         //观看人数
}


上面说了一些立马要用到请求的数据类型,也就是我们的第一步已经实现了,接下来需要考虑的是一次请求,要请求多少数据,在请求不变的情况下怎么加载最新的数据,需要知道的是对于一个用户很多的应用,可能在1s内就有几百万用户在同时上传数据,像instagram,如果是采用简单的按时间把所有上次请求之后的数据都加载下来,你一刷新那就一次得加载超多数据,这是不现实的,那该如何去做这个刷新?我这里的做法也很简单,每次固定加载20条,每次都加在最新数据,这是下拉刷新,还有上拉加载更多的处理办法也差不多,固定加载20条,按时间来加载。毕竟不太懂高大上的大数据,像百万级的数据,等把千级的东西做出来再说,像那么多的数据更多的应该是做分类吧!(我瞎猜的)这里就不瞎掰了,就按上面讲的简单的方法来。

什么是最新数据呢?这得看是怎么存数据的,如果是靠时间来判断是不可靠的,可能谁修改一下服务器时间就乱了(插入数据的时候不会是根据客户端提供的时间,有不同时区的情况,纯按时间来比较的话明显不准确),所以这里我是靠id(数据库id数升序自增)来判断的,想想应该是没什么问题的,黑客能做的也就是冒充用户发送数据,光就发送的数据只要不提供修改id的接口还不足以修改id(要是入侵了服务器直接操作了数据库那我就不管了!算他牛b好了吧),这样就保证只要黑客入侵不了我们的服务器就无法导致我们的服务器数据出错,当然还需要配合使用加密手段,对我们传输的数据进行加密,注意加密不能所有数据都加密,部分加密就行了(一般的加密算法都会使得数据量变大)。

这里我还想了一种保证id不会被改变得办法,就我现在做的这个应用,所有和服务器的通信都是单向的,也就是只有读的操作,这样的话在数据库这边就可以做限制,提供一个只能读的账号就行,如果后续添加了用户上传数据的功能,可以再建一个数据库就行(其实大公司多数据库这种做法很多,主要是为了把数据分类分清楚)。总的来说这种做法限制性还是比较大,如果要使用的话要做好规划。

服务器端如何传数据

大致代码如下:

$sql = "select xx from xx";
$rst = mysql_query($sql);
$arr = array();
while($row=mysql_fetch_array($rst)){
$ret=new一个对象($row['属性名']...);
$arr[]=$ret;
}
echo json_encode($arr);


上述的伪代码大致说一下:首先一个sql语句,随后执行这条sql语句并声明一个数组,循环取出查询出来的数据封装成对象放到数组中,最后输出这个对象数组。服务器端的大致实现就是这样,具体代码看这里:在这里

客户端如何接收数据

我们用了retrofit框架所以这里我们要做的就是声明接口,对retrofit的配置可以看:实现PHP服务器+Android客户端(Retrofit+RxJava)第三天

具体代码如下:

/**
* 加载最新的count条数据,用于下拉刷新和一开始加载的时候
*
* @param count
* @return
*/
@Headers("Cache-Control:max-age=640000")
@GET("headlineitem.php")
Observable<List<HeadlineItem>> getLatestItemInfo(@Query("count") int count);

/**
* 取小于这个id的count条数据,用于加载更多
* @param count
* @param id
* @return
*/
@GET("headlineitem.php")
Observable<List<HeadlineItem>> getItemInfo(@Query("count") int count,@Query("id") int id);


如何加载呢?看这里:

Subscription s = App.getRetrofitInstance().getApiService()
.getLatestItemInfo(AppConfig.headlineItemCount)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<HeadlineItem>>() {
@Override
public void onCompleted() {

}

@Override
public void onError(Throwable throwable) {
Log.d("sqqq", throwable.toString());
}

@Override
public void onNext(List<HeadlineItem> s) {
if(ifClear){
items.clear();
}
Log.d("sqqq",s.size()+"");
items.addAll(s);
view.refresh(false);
}
});


整个项目的代码(目前还没有全部完成,还在持续更新中。。。上传的也是部分):Sqq_Total
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android php