流浪诗人工作室


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

Android NDK开发从入门到放弃

发表于 2017-02-14   |   分类于 NDK   |  

前段时间公司的SDK开发,核心逻辑要改用C/C++(花了点时间把还给老师的,重新拾回),我就把NDK开发相关资料文档整理一下方便你我他。

预备概念:

JNI:

它提供了若干的API实现了Java和其他语言的通信(主要是C/C++),这是JAVA层面的标准,我的理解就是C/C++调用这些接口转换成JAVA能“听”得懂的语言

NDK:

我的理解就是Android里Java和C/C++通信所需要的开发环境工具包(类似于使用JAVA要用JDK)

CMake:

我的理解就是编译工具,类似于Android Studio里的Gradle

如果我理解错误,希望指出。

准备动作:

首先国际惯例最权威官方:googlesamples/android-ndk

CMake:

Android Studio 2.2 更方便地创建JNI项目-CMake

JNI:

Android JNI编程—JNI基础
Android JNI编程—JNI函数大全

C/C++

以前同事,曾经的黑客推荐的几本书和在线文档

在线文档:

C文档
C++文档
C 语言标准函数库速查
C++ 教程(如果不适应cppreference的目录结构可参考这个)

PDF电子书下载:

C语言入门经典.pdf
C.Primer.Plus中文版.pdf
C++11中文版.pdf

起飞:

Android NDK 开发之旅,我只能帮到你这,有googlesamples的例子,有基础概念,有C/C++文档。接下来只能靠你自己了,Just do IT.

后记:

为什么不整理写一篇完整教程呢?我觉得没必要,都是一些概念性的东西和流程化,写了也只是大同小异。所以直接引用

Ok,That’s all,Enjoy it.Good luck to you.

RxJava2 + Retrofit2 优雅简洁封装

发表于 2017-02-11   |   分类于 RxJava   |  

RxJava2 封装主要变化

  • Transformer的变化:RxJava1.X为rx.Observable.Transformer接口, 继承自Func1<Observable<T>, Observable<R>>, RxJava2.X为io.reactivex.ObservableTransformer<pstream, Downstream>,是一个独立的接口。
  • Flowable则是FlowableTransformer,如果你使用Flowable,以下ObservableTransformer替换FlowableTransformer即可。

项目 gitHub 地址

RxJava2 + Retrofit2.jpg

封装方案

1、封装 Rx 线程相关

RxSchedulersHelper:

1
2
3
4
5
6
7
8
9
10
/**
* Created by weiss on 17/1/16.
*/
public class RxSchedulers {
public static <T> ObservableTransformer<T, T> io_main() {
return upstream ->
upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
}

封装后:

1
2
3
Api.getInstance().movieService
.getGankData("Android",1)
.compose(RxSchedulers.io_main());

2、封装 处理服务器返回数据,管理 RxJava生命周期

HttpResult:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* Created by Weiss on 2017/1/11.
*/

public class HttpResult<T> implements Serializable {
public String code;
public String msg;
public boolean hasmore;
public T data;

public static String SUCCESS = "000";
public static String SIGN_OUT = "101";//token验证失败
public static String SHOWTOAST = "102";//显示Toast

public boolean isSuccess() {
return SUCCESS.equals(code);
}

public boolean isTokenInvalid() {
return SIGN_OUT.equals(code);
}

public boolean isShowToast() {
return SHOWTOAST.equals(code);
}

public boolean hasMore() {
return hasmore;
}
}

BaseRxActivity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

/**
* 管理RxJava生命周期,避免内存泄漏
* RxJava处理服务器返回
*
* Created by Weiss on 2016/12/23.
*/

public abstract class BaseRxActivity extends BaseActivity {

private CompositeDisposable disposables2Stop;// 管理Stop取消订阅者者
private CompositeDisposable disposables2Destroy;// 管理Destroy取消订阅者者

protected abstract int getLayoutId();

protected abstract void initView();

/**
* Rx优雅处理服务器返回
*
* @param <T>
* @return
*/
public <T> ObservableTransformer<HttpResult<T>, T> handleResult() {
return upstream ->{
return upstream.flatMap(result -> {
if (result.isSuccess()) {
return createData(result.data);
} else if (result.isTokenInvalid()) {
//处理token失效,tokenInvalid方法在BaseActivity 实现
tokenInvalid();
} else {
return Observable.error(new Exception(result.msg));
}
return Observable.empty();
}

);
};
}

private <T> Observable<T> createData(final T t) {
return Observable.create(subscriber -> {
try {
subscriber.onNext(t);
subscriber.onComplete();
} catch (Exception e) {
subscriber.onError(e);
}
});
}

public boolean addRxStop(Disposable disposable) {
if (disposables2Stop == null) {
throw new IllegalStateException(
"addUtilStop should be called between onStart and onStop");
}
disposables2Stop.add(disposable);
return true;
}

public boolean addRxDestroy(Disposable disposable) {
if (disposables2Destroy == null) {
throw new IllegalStateException(
"addUtilDestroy should be called between onCreate and onDestroy");
}
disposables2Destroy.add(disposable);
return true;
}

public void remove(Disposable disposable) {
if (disposables2Stop == null && disposables2Destroy == null) {
throw new IllegalStateException("remove should not be called after onDestroy");
}
if (disposables2Stop != null) {
disposables2Stop.remove(disposable);
}
if (disposables2Destroy != null) {
disposables2Destroy.remove(disposable);
}
}

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (disposables2Destroy != null) {
throw new IllegalStateException("onCreate called multiple times");
}
disposables2Destroy = new CompositeDisposable();
}

public void onStart() {
super.onStart();
if (disposables2Stop != null) {
throw new IllegalStateException("onStart called multiple times");
}
disposables2Stop = new CompositeDisposable();
}

public void onStop() {
super.onStop();
if (disposables2Stop == null) {
throw new IllegalStateException("onStop called multiple times or onStart not called");
}
disposables2Stop.dispose();
disposables2Stop = null;
}

public void onDestroy() {
super.onDestroy();
if (disposables2Destroy == null) {
throw new IllegalStateException(
"onDestroy called multiple times or onCreate not called");
}
disposables2Destroy.dispose();
disposables2Destroy = null;
}
}

封装后 (BaseRxActivity的子类使用):

1
2
3
4
5
6
addRxDestroy(Api.getInstance().movieService
.getGankData("Android",1)
.compose(RxSchedulers.io_main())
.compose(handleResult())
.省略
);

handleResult为什么不新建一个类处理呢?因为很多异常处理需要context对象,或者和BaseActivity有千丝万缕的联系,BaseRxActivity继承BaseActivity可以很简洁优雅处理各种异常。比如token失效,是需要跳转到登录页面的。在新建一个类中,不能持有context对象,只能使用Application的Context,同时方便与Activity通信交互满足各种需求。BaseRxActivity还可以管理RxJava生命周期。

3、异常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

/**
* Created by Weiss on 2017/2/9.
*/

public class RxException<T extends Throwable> implements Consumer<T> {

private static final String TAG = "RxException";

private static final String SOCKETTIMEOUTEXCEPTION = "网络连接超时,请检查您的网络状态,稍后重试";
private static final String CONNECTEXCEPTION = "网络连接异常,请检查您的网络状态";
private static final String UNKNOWNHOSTEXCEPTION = "网络异常,请检查您的网络状态";

private Consumer<? super Throwable> onError;
public RxException(Consumer<? super Throwable> onError) {
this.onError=onError;
}

/**
* Consume the given value.
*
* @param t the value
* @throws Exception on error
*/
@Override
public void accept(T t) throws Exception {
if (t instanceof SocketTimeoutException) {
Log.e(TAG, "onError: SocketTimeoutException----" + SOCKETTIMEOUTEXCEPTION);
ToastUtils.show(SOCKETTIMEOUTEXCEPTION);
onError.accept(new Throwable(SOCKETTIMEOUTEXCEPTION));
} else if (t instanceof ConnectException) {
Log.e(TAG, "onError: ConnectException-----" + CONNECTEXCEPTION);
ToastUtils.show(CONNECTEXCEPTION);
onError.accept(new Throwable(CONNECTEXCEPTION));
} else if (t instanceof UnknownHostException) {
Log.e(TAG, "onError: UnknownHostException-----" + UNKNOWNHOSTEXCEPTION);
ToastUtils.show(UNKNOWNHOSTEXCEPTION);
onError.accept(new Throwable(UNKNOWNHOSTEXCEPTION));
} else {
Log.e(TAG, "onError:----" + t.getMessage());
onError.accept(t);
}
}
}

封装后 (BaseRxActivity的子类使用):

1
2
3
4
5
6
7
addRxDestroy(Api.getInstance().movieService
.getGankData("Android",1)
.compose(RxSchedulers.io_main())
.compose(handleResult())
.subscribe(httpResult -> adapter.setItems(httpResult.data),
new RxException<>(e ->e.printStackTrace()))
);

4、多页请求封装

实体类:

1
2
3
4
5
6
7
8
9
10
11
12
/**
* Created by Weiss on 2017/1/20.
*/

public class Gank extends BaseListEntity {
@Override
public Flowable<HttpResult<List<Gank>>> getPage(int page) {
return GankApi.getInstance().service.getGankData(param.get("gank"), page)
.compose(RxSchedulers.io_main());
}

}

实体类继承 BaseListEntity,实现getPage方法即可。

UI视图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MainActivityFragment extends BaseRxFragment {
@BindView(R.id.baseRecyclerView)
PtrRecyclerView ptrRecyclerView;

private MultiTypeAdapter adapter;

public MainActivityFragment() {
}


@Override
protected int getLayoutId() {
return R.layout.fragment_main;
}

@Override
protected void initView() {
ptrRecyclerView.setParam("gank","Android");
adapter = new MultiTypeAdapter();
adapter.register(Gank.class,new GankViewProvider());
ptrRecyclerView.setAdapter(adapter,new Gank());
}
}

只需要写一个适配器和实体类,轻松实现多页请求,PtrRecyclerView下拉刷新和上拉加载自动获取数据。
PtrRecyclerView目前只是简单实现下拉刷新和上拉加载,有空会完善,当然例子也会完善。

后记

还可以封装网络加载对话框,这个看个人喜好,同样以上封装同样可以看个人喜好和项目需求自由组装。
RxJava2 + Retrofit2 封装 giithub 地址

相关链接

RxJava 2.0有什么不同(译)

探索专为 Android 而设计的 RxJava 2

RxJava2 + Retrofit2 开发框架

Slack里一些有意思的讨论

发表于 2017-02-09   |   分类于 笔记   |  

本文记载Slack里大神们一些有意思的讨论

auto verify

QQ图片20170210225036.png

Android源码笔记

发表于 2017-02-08   |   分类于 笔记   |  

LinearLayoutManager

LinearLayoutManager 源码构造方法需要传Context,但是它根本没有用到
Paste_Image.png
这是兼容设计,layout manager,将来很可能用到Context,那时不至于破坏接口的兼容性,修改旧版本的代码。

【RWBY】写在未完结的日子——蒙特·乌姆

发表于 2015-11-19   |   分类于 ◇﹎话℡   |  

【RWBY】Red trailer

【RWBY】White trailer(从RUBY和Weiss的预告开始入坑了,坐等BY的日子)

【RWBY】Black trailer

【RWBY】Yellow trailer

【RWBY R.I.P】感谢你曾来过这个世界

【RWBY第一季完结纪念】灵魂悸动

【RWBY】Ruby.Weiss.Blake.Yang.

我们将会用自己的方式来纪念蒙特。相比要鲜花和礼物,我们更希望大家可以做一些更有意思的事情。希望你们可以运用自己的想象力让这个世界变得更加美好。如果你们和我们一样熟悉蒙特,你肯定会知道,这也是他的愿望。——【马特讣告】


Let Red fills your dream with roses
让红色的玫瑰点满你永远的梦境

Let White make your path to the heaven with ice
让白色的冰雪铺盖通往天堂的道路

Let Black night travel with you
让黑色的夜晚伴随你前行的身姿

Let Yellow shines at the end
让金色的光芒闪耀在这旅途的终点

Good night, the one who makes our dreams
晚安,我们的造梦师

Monty Oum

Wish sunshine and rainbows with you
愿阳光和彩虹永远与你同在

We love you until end of this century
我们爱你,直到这个世纪末

Goodbye and thank you
谢谢,还有再见

原文地址:http://www.bilibili.com/topic/568.html

12
此人丶不用抒情

此人丶不用抒情

7 日志
5 分类
9 标签
GitHub 简书
© 2017 此人丶不用抒情
由 Hexo 强力驱动
主题 - NexT.Mist