RxJava2+Retrofit2+MVP+lamdba仿微信朋友圈Demo

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); 
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值