1.吹风湿篇
最近学Rxjava2,但工作上未能使用,想想做个Demo来记录下,总结学习的新知识,分别用到Rxjava2,Retrofit2,Okhttp3,Glide,MVP,java8的新特性Lamdba。
确定想法以后,就开始写代码,但我又不想造轮子写界面,所以在github 看到一个仿朋友圈的demo,仿微信实现的朋友圈,模拟与后台交互实现了点赞、评论、删除等功能,RecyclerView可以根据键盘的显示或隐藏实现联动。 增加短视频拍摄功能(趣拍标准版SDK) 与后台交互采用mvp模式。
Github传送门 CircleDemo
找到界面,但问题出现了CircleDemo的数据是使用本地,但我要练手Retrofit2,Okhttp3必须要服务器呀,想想用什么写服务器呢,PHP,javaEE, beego,Node.js…一堆写服务器的方式在脑海中转;javaEE太庞大了,php,Node.js不会,好吧,只能选择Beego了,简单,容易(额,我不是在打广告)
Beego 传送门 https://beego.me/
所以下载我编写的服务器的同志们,要麻烦配置下go语言开发环境,不懂得go语言没所谓,会配置运行起来用就行。
技术篇
1.go语言开发环境配置
(1)下载链接 http://www.golangtc.com/download
(2)下载后直接双击msi文件安装,默认安装在c:\go
(3)安装完成后默认会在环境变量 Path 后添加 Go 安装目录下的 bin 目录 C:\Go\bin\,并添加环境变量 GOROOT,值为 Go 安装根目录 C:\Go\
(4).验证是否安装成功,在运行中输入 cmd 打开命令行工具,在提示符下输入 go,出现下图就表示成功了
2.运行beego服务器
服务器代码Github下载 (包括服务器与依赖库代码)
https://github.com/credit03/RxJavaServer
若依赖库不能使用,请使用下面csdn下载方式下载
由于文件过大,csdn限制60mb,所以服务器代码与依赖库分开上传。
(1)先下载依赖库,下载链接 http://download.csdn.net/detail/u013217757/9782025
(2)下载(DevSuroce)依赖库成功,解压到go安装的根目录
(3)服务器主要代码,下载链接
http://download.csdn.net/detail/u013217757/9782038
下载服务器主要代码后解压到一个没有中文的目录,我的目录如下
(4)使用cmd ,cd 到src目录,例如我的:
d:
cd D:\RxJavaCode\Server\RxJavaServer\src
(5) 然后 输入beego运行命令 bee run
就这样服务器就运行了,运行成功的样子如下:
测试 http://localhost:8080/login?mobile=13800138000&pwd=123456
有同学注意到为啥不用配置数据库之类的东西呢….,答案是使用sqlite3数据库,没错就是它了,在beego配置使用sqlite3数据库,当然也可以使用mysql,看文档配置就行
好的,服务器小点到现在结束,不懂的留言。
3,APP技术篇
(1)下载app代码,下载链接(本来是想上传到Github但上传失败,捣蛋了一个小时无法解决,放弃了)
http://download.csdn.net/detail/u013217757/9782232
(2) 目录结构
(3) 使用android studio打开,修改服务器ip,运行安装就行,运行效果如下:
运行时有的图片是无法加载,因为我在服务器中删除了6.jpg和16.jpg,若加载到这两张图片就是空白。解决方法,在服务器的static目录下的img目录(static/img/)添加两张图片
(4)重构了CircleDemo中Aadpater与ViewHolder,修改了上下刷新界面,添加了发表图文,接收分享,修改视频录制功能,等功能。用到技术如下:
使用mvp构架项目
使用RxJava2+Retrofit2 +Okhttp3实现网络访问
使用轻量级缓存框架——ACache(ASimpleCache)
使用SwipeToLoadLayout作上下拉刷新界面
使用java 8的lamdba特性创建单方法回调
太哆嗦了,使用库就如下了…
//Rxjava for android
compile 'io.reactivex.rxjava2:rxjava:2.0.5'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
// compile 'org.xutils:xutils:3.3.40'
// compile 'com.squareup.picasso:picasso:2.5.2'
//photoview
compile 'com.github.chrisbanes:PhotoView:1.3.1'
//glide
compile 'com.github.bumptech.glide:glide:3.7.0'
//如果你的网络请求底层使用了Okhttp的话,那么可以指定这个让Glide网络层使用Okhttp
compile('com.github.bumptech.glide:okhttp3-integration:1.4.0') {
exclude group: 'glide-parent'
}
//retrofit
compile 'com.squareup.retrofit2:retrofit:2.1.0'
//Gson converter
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
//RxJava2 retrofit Adapter
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
//okhttp3
compile 'com.squareup.okhttp3:okhttp:3.4.1'
//okhttp3日志拦截器
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
//自动注解 butterknife
compile 'com.jakewharton:butterknife:5.1.1'
//上下拉刷新 SwipeToLoadLayout
compile 'com.github.Aspsine:SwipeToLoadLayout:1.0.4'
compile 'com.android.support:design:25.1.0'
//加载进度条
compile 'com.mikhaellopez:circularprogressbar:1.1.1'
// compile 'com.github.waynell:VideoListPlayer:1.4'
//视频录制, 利用FFmpeg视频录制与压缩处理
compile 'com.mabeijianxi:small-video-record:1.0.8'
//图片选择器
compile(project(':PhotoPicker')) {
// exclude group: 'com.android.support', module: 'recyclerview'
exclude group: 'com.github.bumptech.glide',
module: 'glide'
}
lamdba 简单总结,本来我也不会lamdba 语句的,但学Rxjava时,时不时就来一段lamdba语句,烦了,学RxJava学了一天,花了一小时去学lamdba,看上去好高大上的样子,虽然简洁,便不方便阅读。下面是我的简单总结,对我目前来说够用状态。
/**
* JAVA8 的Lambda表达式 总结:
* 1.只用一个回调方法的接口可以使用 Lambda表达式
* -----------------------------
* 2.没有带参和没有返回值的方法:
* void onclick(){
* } - Lambda表达式-> ()->{}
* ------------------------------
* 3. 单个带参和没有返回值的方法:
* void onclick(View v){
* Log.e(v.getid());
* }
* Lambda表达式:
* 3.1,指定参数类型
* (View v)->{ Log.e(v.getid());}
* 3.2,直接给Lambda推导
* v->{ Log.e(v.getid());}
* 3.3更精简的方法
* v->Log.e(v.getid());
*
* 以上的功能都一致的
*----------------------------------
* 4.多个带参和没有返回值的方法:
* void onclick(View v,int position){
* Log.e(v.getid()+" pos:"+position);
* }
* Lambda表达式:
* 和3的使用方式一样:
* (View v,int pos)->{Log.e(v.getid()+" pos:"+pos)};
* 或(v,pos)->Log.e(v.getid()+" pos:"+pos);
*
* 5.有返回值的方法:
* public int add(int a,int b){
* return a+b;
* }
* 注意了:有返回值的要加{},不能忽略{}
* (a,b)->{return a+b;}
*
*/
TestLba t1= new TestLba() {
@Override
public void onclick(int a, int b) {
Log.e(TAG, "使用JAVA8 的Lambda表达式教程onCreate:>>>>>>> " + (a + b));
}
};
TestLba t2= (a, b) ->
Log.e(TAG, "使用JAVA8 的Lambda表达式教程onCreate:>>>>>>> " + (a + b));
t1.onclick(1, 2);
t2.onclick(100, 200);
在Android studio 使用 lamdba 配置,配置下面两项就可以使用 lamdba语句了
1.在总项目的build.gradle(不是app的build.gradle)配置下
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
//配置支持lamdba
classpath 'me.tatarka:gradle-retrolambda:3.2.5'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
2.在app的build.gradle配置下
apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda' // java8 语法支持
Rxjava2 没啥好总结,哈哈,不会Rxjava2 的同学们,android使用Rxjava 配置下面两个,教程传送门如下:
compile 'io.reactivex.rxjava2:rxjava:2.0.5'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
给初学者的RxJava2.0教程(一)
给 Android 开发者的 RxJava 详解
关于RxJava2.0你不知道的事
RxJava2.0官方Demo
ReactiveX/RxJava文档中文版
楼主就看“给初学者的RxJava2.0教程”与“ReactiveX/RxJava文档中文版”学会Rxjava2的。
Retrofit2 总结,retrofit非常适合于restful url格式的请求,更多使用注解的方式提供功能
与okhttp3搭配是绝配,因为retrofit的底层使用okhttp
支持与Rxjava配置使用
//retrofit
compile 'com.squareup.retrofit2:retrofit:2.1.0'
//Gson converter
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
//RxJava2 retrofit Adapter
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
//okhttp3
compile 'com.squareup.okhttp3:okhttp:3.4.1'
//okhttp3日志拦截器
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
在当前项目中问题点就是,服务器要cookie授权才可以获取数据,retrofit一直没有提交,不知道是我代码错误,还什么问题,目前解决方法,Okhttp3添加拦截器,在响应时,获取cookie持久化到本地;在请求时,添加cookie到请求头
package com.guoyi.circle.request;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import java.io.IOException;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.functions.Function;
import okhttp3.Interceptor;
import okhttp3.Response;
/**
* Created by Credit on 2017/3/14.
* 响应时,获取cookie拦截器
*/
public class GetOkHttpCookieInterceptor implements Interceptor {
private static final String TAG = "GetOkHttpCookie";
private Context context;
public GetOkHttpCookieInterceptor(Context context) {
super();
this.context = context;
}
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
//这里获取请求返回的cookie
if (!originalResponse.headers("Set-Cookie").isEmpty()) {
final StringBuffer cookieBuffer = new StringBuffer();
//最近在学习RxJava,这里用了RxJava的相关API大家可以忽略,用自己逻辑实现即可.大家可以用别的方法保存cookie数据
List<String> headers = originalResponse.headers("Set-Cookie");
SharedPreferences sharedPreferences = context.getSharedPreferences("cookie", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
Observable.fromIterable(headers)
.map(new Function<String, String>() {
@Override
public String apply(String s) throws Exception {
String[] cookieArray = s.split(";");
return cookieArray[0];
}
})
.subscribe(cookie -> {
Log.e(TAG, " 保存 cookie ---intercept: " + cookie);
String[] split = cookie.split("=");
editor.putString(split[0], cookie + ";");
// cookieBuffer.append(cookie).append(";");
});
editor.commit();
}
return originalResponse;
}
}
package com.guoyi.circle.request;
import android.content.Context;
import android.content.SharedPreferences;
import java.io.IOException;
import io.reactivex.Observable;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
/**
* Created by Credit on 2017/3/14.
* 请求时,添加cookie拦截器
*/
public class AddOkHttpCookieIntercept implements Interceptor {
private Context context;
public AddOkHttpCookieIntercept(Context context) {
super();
this.context = context;
}
@Override
public Response intercept(Chain chain) throws IOException {
final Request.Builder builder = chain.request().newBuilder();
SharedPreferences sharedPreferences = context.getSharedPreferences("cookie", Context.MODE_PRIVATE);
//最近在学习RxJava,这里用了RxJava的相关API大家可以忽略,用自己逻辑实现即可
/**
* beegosessionID --beego默认返回的seession key
*
*this.Ctx.SetCookie("mobile", u.Mobile, maxTime, "/")
this.Ctx.SetCookie("pwd", u.Pwd, maxTime, "/")
服务器对应的cookie
*/
String beegosessionID = sharedPreferences.getString("beegosessionID", "");
String mobile = sharedPreferences.getString("mobile", "");
String pwd = sharedPreferences.getString("pwd", "");
Observable.just(beegosessionID, mobile, pwd)
.subscribe(cookie -> {
//添加cookie
builder.addHeader("Cookie", cookie);
});
return chain.proceed(builder.build());
}
}
Retrofit2 教程
你真的会用Retrofit2吗?Retrofit2完全教程
Retrofit2 完全解析 探索与okhttp之间的关系
Retrofit2 官方Github主页
Retrofit项目官方文档
整个项目总结
1.上传图片压缩,当在wifi情况下单张图片最大256kb,在手机网络情况下最大128kb。
2.使用自定义GlideModule,通过Glide加载视频文件,缓存原理和图片缓存一样。
3.学会使用mvp模式。
4.加深Rxjava2与Retrofit2使用方式 。
5.半年没有写过go语言了,复习了go与beego框架的使用。
6.以前没有接触过setMovementMethod,学到了使用的作用,添加一个动作(滑动,点击等等)改变View的状态,例如点击改变背景,功能和selector差不多,学习链接:http://blog.csdn.net/lincyang/article/details/7259322
为TextView设置链接:、
当文字中出现URL、E-mail、电话号码等的时候,我们为TextView设置链接。总结起来,一共有4种方法来为TextView实现链接。我们一一举例介绍;
1. 在xml里添加android:autoLink属性。
android:autoLink :的可选值:none/web/email/phone/map/all,分别代表将当前文本设置为:
普通文本/URL/email/电话号码/map/自动识别,文本显示为可点击的链接。其中:设置为all时,系统会自动根据你的文本格式识别文本类型,如:http为web,tel为电话等;当然,以上内容也可以在Java代码中完成,用法为tv.setAutoLinkMask(Linkify.ALL)。
2. 将显示内容写到资源文件,一般为String.xml中,并且用<a>标签来声明链接,然后激活这个链接,激活链接需要在Java代码中使用setMovementMethod()方法设置TextView为可点击。
3. 用Html类的fromHtml()方法格式化要放到TextView里的文字。然后激活这个链接,激活链接需要在Java代码中使用setMovementMethod()方法设置TextView为可点击。
4. 用Spannable或实现它的类,如SpannableString。与其他方法不同的是,Spannable对象可以为个别字符设置链接(当然也可以为个别字符设置颜色、字体等,实现某些字符高亮显示的效果等)。这个方法同样需要在Java代码中使用setMovementMethod()方法设置TextView为可点击。
TextView中设置多种字体大小
这是项目中经常遇到的,比如UI是这样的:
Android实战技巧之文本与布局
像这样的两种字体,要如何处理呢?需要用到android.text命名空间下的一些与spannable相关的类和接口。例子如:
//[java] view plain copy 在CODE上查看代码片派生到我的代码片
String text = "Android实战技巧之文本与布局";
int start = text.indexOf('之');
int end = text.length();
Spannable textSpan = new Spannable(text);
textSpan.setSpan(new AbsoluteSizeSpan(20),0,start,Spannable.SPAN_INCLUSIVE_INCLUSIVE);
textSpan.setSpan(new AbsoluteSizeSpan(12),start,end,Spannable.SPAN_INCLUSIVE_INCLUSIVE);