导图社区 移动开发方案总结
移动开发方案总结,包括基础知识、BOOK、开源组件、平台框架、架构、、Andoid、小程序、开发工具等等。
编辑于2022-05-17 22:02:52移动开发方案总结
基础
Java基础
浅析Java中的final关键字
注释说明
@author 对类的说明 标明开发该类模块的作者
@version 对类的说明 标明该类模块的版本
@see 对类、属性、方法的说明 参考转向,也就是相关主题
@see <a href=“http://google.com”>http://google.com</a>
@param 对方法的说明 对方法中某参数的说明
@return 对方法的说明 对方法返回值的说明
@exception 对方法的说明 对方法可能抛出的异常进行说明
@Time2012-11-20 15:02:29
@since
@description: 这是用户类
@methodsName
@link 语法{@link package.class#member label}
java中for和foreach的区别
区别
性能比较
开发点滴
byte[]与十六进制字符串相互转换
Array和及平均数
Kotlin
数据结构
链表
队列
栈
数组
哈希表
HashMap
二分查找
二叉树
N叉树
B树
数据结构和算法
结构
线性表
数组
链表
单链表
双向链表
循环链表
双向循环链表
静态链表
栈
顺序栈
链式栈
队列
普通队列
双端队列
阻塞队列
并发队列
阻塞并发队列
散列表
散列函数
冲突解决
链表法
开发寻址
其他
动态扩容
位图
树
二叉树
平衡二叉树
二叉查找树
平衡二叉查找树
AVL树
红黑树
完全二叉树
满二叉树
多路查找树
B树
B+树
2-3树
2-3-4树
堆
小顶堆
大顶堆
优先级队列
斐波那契堆
二项堆
其他
树状数组
线段树
图
图的存储
邻接矩阵
邻接表
拓扑排序
最短路径
关键路径
最小生成树
二分图
最大流
复杂度分析
空间复杂度
时间复杂度
最好
最坏
平均
均摊
基本算法思想
贪心算法
分治算法
动态规划
回溯算法
枚举算法
排序
O(n*2)
冒泡
插入排序
选择
希尔
O(nlogn)
并归
快排
堆排序
O(n)
计数排序
基数排序
桶排序
搜索
深度优先搜索
广度优先搜索
启发式搜索
查找
线性表查找
树结构查找
散列表查找
字符串匹配
朴素
KMP
Robin-Karp
Boyer-Macore
AC自动机
Trie
后缀数组
其他
数论
计数几何
概率分析
并查集
拓扑网络
矩阵运算
线性规划
leetcode
递归
接雨水
剑指offer
https://www.jianshu.com/p/4a889d052127
题目一:找出数组中重复的数字
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。 ``` public class Solution { // Parameters: // numbers: an array of integers // length: the length of array numbers // duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation; // Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++ // 这里要特别注意~返回任意重复的一个,赋值duplication[0] // Return value: true if the input is valid, and there are some duplications in the array number // otherwise false public boolean duplicate(int numbers[], int length, int [] duplication) { if (numbers == null || length <= 0) { return false; } for (int i = 0; i < length; i++) { if (numbers[i] < 0 || numbers[i] > length - 1) { return false; } while (numbers[i] != i) { if (numbers[numbers[i]] == numbers[i]) { duplication[0] = numbers[i]; return true; } else { int temp = numbers[i]; numbers[i] = numbers[temp]; numbers[temp] = temp; } } } return false; } } ``` 复杂度分析 时间复杂度:O(n)。 空间复杂度:O(1)。
其他算法
github开源上有配图的java算法
设计模式
设计模式六大原则
开闭原则(Open Close Principle)
类、 模块、 函数 等 应该 是 可以 拓展 的, 但是 不可 修改。
单一职责
就 一个 类 而言, 应该 仅有 一个 引起 它 变化 的 原因。
里氏代换原则(Liskov Substitution Principle)
所有 引用 基 类( 父 类) 的 地方 必须 能 透明 地 使用 其 子类 的 对象。
依赖倒转原则(Dependence Inversion Principle)
针对接口编程,依赖于抽象而不依赖于具体
接口隔离原则(Interface Segregation Principle)
一个 类 对 另一个 类 的 依赖 应该 建立 在最 小的 接口 上。
迪米特法则,又称最少知道原则(Demeter Principle)
一个 软件 实体 应当 尽可能 少地 与其 他 实体 发生 相互作用。
合成复用原则(Composite Reuse Principle)
创建型模式
工厂模式
抽象工厂模式
单例模式
静态 内 部类 单 例 模式
静态内部类 ``` public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } } ```
建造者模式
原型模式
结构型模式
适配器模式
桥接模式
过滤器模式
组合模式
装饰器模式
外观模式
享元模式
代理模式
行为型模式
责任链模式
命令模式
解释器模式
迭代器模式
中介者模式
备忘录模式
观察者模式
状态模式
策略模式
模板模式
访问者模式
J2EE模式
MVC 模式
业务代表模式
组合实体模式
数据访问对象模式
前端控制器模式
拦截过滤器模式
服务定位器模式
传输对象模式
空对象模式
多线程
线程池
ThreadPoolUtil 参考 [多线程和线程池](https://www.jianshu.com/p/b290de65bf79) [Android多线程:线程池ThreadPool 全面解析](https://www.jianshu.com/p/0e4a5e70bf0e) [ 线程池ThreadPoolExecutor详解](https://juejin.im/post/5a7d4fb0f265da4e7071b99b) ``` import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; /** * Created by lichongmac@163.com on 2019-08-02. */ public class ThreadPoolUtil { ///////////////////////////////////////////////////////////////////// ////////////// 定长线程池 //////////////////////// ///////////////////////////////////////////////////////////////////// // 1. 创建定长线程池对象 & 设置线程池线程数量固定为3 public static ExecutorService fixedThreadPool = null; //默认固定线程数 private final static int defaultNThreads = 3; public static void setFixedThreadPool(int nThreads) { fixedThreadPool = Executors.newFixedThreadPool(nThreads); } /** * 特点:只有核心线程 & 不会被回收、线程数量固定、任务队列无大小限制(超出的线程任务会在队列中等待) * 应用场景:控制线程最大并发数 * 具体使用:通过 Executors.newFixedThreadPool() 创建 */ public static Executor getFixedThreadPool() { if (null == fixedThreadPool) { fixedThreadPool = Executors.newFixedThreadPool(defaultNThreads); } return fixedThreadPool; } ///////////////////////////////////////////////////////////////////// //////////////定时线程池(ScheduledThreadPool ) ///////////////////////////////////////////////////////////////////// // 特点:核心线程数量固定、非核心线程数量无限制(闲置时马上回收) // 应用场景:执行定时 / 周期性 任务 // 使用:通过Executors.newScheduledThreadPool()创建 // 3. 向线程池提交任务:schedule() //scheduledThreadPool.schedule(task, 1, TimeUnit.SECONDS); // 延迟1s后执行任务 //scheduledThreadPool.scheduleAtFixedRate(task,10,1000,TimeUnit.MILLISECONDS);// // 延迟10ms后、每隔1000ms执行任务 // //// 4. 关闭线程池 //scheduledThreadPool.shutdown(); // // 1. 创建 定时线程池对象 & 设置线程池线程数量固定为5 private static ScheduledExecutorService scheduledThreadPool; public static ScheduledExecutorService getScheduledThreadPool() { if (null == scheduledThreadPool) { scheduledThreadPool = Executors.newScheduledThreadPool(5); } return scheduledThreadPool; } ///////////////////////////////////////////////////////////////////// //////////////可缓存线程池(CachedThreadPool) ///////////////////////////////////////////////////////////////////// // 特点:只有非核心线程、线程数量不固定(可无限大)、灵活回收空闲线程(具备超时机制,全部回收时几乎不占系统资源)、新建线程(无线程可用时) // // // 任何线程任务到来都会立刻执行,不需要等待 // // // 应用场景:执行大量、耗时少的线程任务 // 使用:通过Executors.newCachedThreadPool()创建 // 1. 创建可缓存线程池对象 //cachedThreadPool.execute(task); // //// 4. 关闭线程池 //cachedThreadPool.shutdown(); //当执行第二个任务时第一个任务已经完成 //那么会复用执行第一个任务的线程,而不用每次新建线程。 private static ExecutorService cachedThreadPool = null; public static ExecutorService getCachedThreadPool() { if (null == cachedThreadPool) { cachedThreadPool = Executors.newCachedThreadPool(); } return cachedThreadPool; } ///////////////////////////////////////////////////////////////////// //////////////单线程化线程池(SingleThreadExecutor) ///////////////////////////////////////////////////////////////////// // 特点:只有一个核心线程(保证所有任务按照指定顺序在一个线程中执行,不需要处理线程同步的问题) // // 应用场景:不适合并发但可能引起IO阻塞性及影响UI线程响应的操作,如数据库操作,文件操作等 // // 使用:通过Executors.newSingleThreadExecutor()创建 // 1. 创建单线程化线程池 private static ExecutorService singleThreadExecutor = null; public static ExecutorService getSingleThreadExecutor() { if (null == singleThreadExecutor) { singleThreadExecutor = Executors.newSingleThreadExecutor(); } return singleThreadExecutor; } public static void shutdown(){ if(null!=fixedThreadPool) { fixedThreadPool.shutdown(); } if(null!=scheduledThreadPool) { scheduledThreadPool.shutdown(); } if(null!=cachedThreadPool) { cachedThreadPool.shutdown(); } if(null!=singleThreadExecutor) { singleThreadExecutor.shutdown(); } } } ```
开发环境
Kotlin
Retrofit+RxJava, 开启 LiveData+Retrofit
Dart
Book
三步读书法
同一个技能方向按照难度选取3到5本书阅读,其中最好的书读3遍
碎片化时间系统学习
要想真正掌握一本书的核心内容,需要读三遍。第一遍:细读,目的在于完整阅读全书,并且划出重点,写上读书笔记;一个月后读第二遍:扫读,主要快速翻阅第一遍阅读时做的笔记和划的重点,目的在于加深记忆;半年后第三遍:忆读,读的时候只看目录,然后去回想内容,如果回想不起来,再去进行扫读。这样三遍下来,基本上一本书的核心内容就能够很好的吸收。
Android进阶之光
目录摘要
Android新特性
替换 ListView 和 GridView 的 RecyclerView
Palette
运行时权限机制
PermissionsDispatcher(见框架)
MaterialDesign
Snackbar
TextInputLayout
FloatingActionButton
View体系
多线程编程
安全地终止线程
同步
volatile
线程池
AsyncTask解析
网络框架
volley
okHttp
Retrofit
设计模式(见基础部分->设计模式)
事件总线
eventBus
otto
函数响应式编程
Rxjava
注解与依赖框架
butterKnife
Dagger2
注解定义与使用
依赖定义与使用
应用架构设计
MVC模式
MVP模式
MVVM模式
系统架构与MediaPlay框架
Android应用性能优化最佳实践
硬件加速控制级别
卡顿监控与实现
自定义Printer
给UI主线程发定时任务
开源组件
Retrofit 2.0
这是一份全面 & 详细的Retrofit 2.0 源码分析指南
视频解说
[Retrofit网络库](https://www.imooc.com/learn/1000) [破解Retrofit](https://www.imooc.com/learn/1128)
动态请求头
## 静态请求头\动态请求头 ``` @GET Call<WeatherWrapper> weather(@Header("apikey") String apikey, @Url String url, @Query("cityname") String cityName); ``` ``` @GET Call<WeatherWrapper> weather(@HeaderMap Map<String, String> headers, @Url String url, @Query("cityname") String cityName); ``` ## 在OkHttp的拦截器中管理请求头 ``` //重写请求头 okHttpClientBuilder.addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request(); Request.Builder requestBuilder = original.newBuilder() .header("token", "xxx") .header("token", "yyy"); Request request = requestBuilder.build(); return chain.proceed(request); } }); //不重写请求头 okHttpClientBuilder.addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request(); Request.Builder requestBuilder = original.newBuilder() .header("platform", "platform")//平台 .header("sysVersion", "sysVersion")//系统版本号 .header("device", "device")//设备信息 .header("screen", "screen")//屏幕大小 .header("uuid", "uuid")//设备唯一码 .header("version", "version")//app版本 .header("apiVersion", "apiVersion")//api版本 .header("token", "token")//令牌 .header("channelId", "channelId")//渠道 .header("networkType", "networkType");//网络类型 Request request = requestBuilder.build(); return chain.proceed(request); } }); ```
RxJava2.X
这可能是最好的RxJava 2.x 教程(完结版
okhttp3.0
子主题
OKHttpFinal
拦截器
LitePal
一些使用方式
[Litepal使用详解](https://blog.csdn.net/pigdreams/article/details/69330946) [体验LitePal的查询艺术](https://blog.csdn.net/guolin_blog/article/details/40153833) [LitePal的存储操作](https://blog.csdn.net/guolin_blog/article/details/39345833) [数据库高手秘籍](https://blog.csdn.net/sinyu890807/column/info/android-database-pro) [litepal数据库多条件+模糊搜索](https://blog.csdn.net/elinor333/article/details/83273297)
butterknife
``` @BindArray(R.array.setting_inn_out) String[] setInnOut; @OnClick(R.id.real_setting_back) public void back() { finish(); } @OnCheckedChanged(value = R.id.switch_set_debug) void setDebug(boolean checked) { DebugHelper.getInstance().setDebug(checked); } @OnTextChanged(value = R.id.et_open_gate_sign_during, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) void setOpenGateSignDuring(Editable s) { String time = s.toString(); if (CheckNull.isNull(time)) { return; } SPHelper.setOpenGateSignDuring(Float.valueOf(time)); } @OnItemSelected(value = R.id.spinner_int_out, callback = OnItemSelected.Callback.ITEM_SELECTED) void setInnerOrOut(int pos) { switch (pos) { case 0: SPHelper.setInnOrOut(Constant.DIRECTION_OUT); break; case 1: SPHelper.setInnOrOut(Constant.DIRECTION_INT); break; default: new RuntimeException("未处理的类别:" + setInnOut[pos]); } } ```
implementation 'com.jakewharton:butterknife:8.4.0'<br> annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
AST
ButterKnife Zelezny插件的安装与使用
activity和Fragment中使用的区别
Dagger2
PermissionsDispatcher
Glide
Gson
使用
List<Person> persons = gson.fromJson(json, new TypeToken<List<Person>>() {<br> }.getType());//对于不是类的情况,用这个参数给出
联系人列表
TensorFlow
Lottie
平台框架
Flutter
android 和 flutter 混合开发
开发文档
[dev](https://flutter.dev/) [中文](https://flutter-io.cn/)
开源项目
阿里练习项目
GSYGithubAppFlutter
Flutter-Notebook
### [中文版](https://github.com/OpenFlutter/Flutter-Notebook/blob/master/README.md) | [English](https://github.com/OpenFlutter/Flutter-Notebook/blob/master/readme_english.md)  ## flutter_notebook有什么 flutetr_note_book有许多flutter相关功能demo的集合,它能够帮助您快速学习一些零碎的知识,本项目将会不定期更新。 如果您觉得有用的话可以Watch该项目,之后更新会自动通知您。 ## 收集更多优秀样例 ### 本项目大多为了提供一些问题的解决思路,如果您有更好的实现方式或者好的创意,欢迎提交PR! ## 如何下载单个项目 将单个项目下url复制粘贴到下面这个中,将会自动生成下载文件: [DownGit](https://minhaskamal.github.io/DownGit/#/home) ## 目前包含以下demo: ### 官方控件系列 #### 视图 - [BottomNavigationBar底部导航](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/flutter_bottomnavigationbar) - [BottomAppBar底部导航](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/bottom_appbar_demo) - [自定义路由样式](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/custom_router_transition) - [高斯模糊(毛玻璃)](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/frosted_glass_style_demo) - [切换页面,保持各页面状态](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/keep_alive_demo) - [制作一个精美的Material风格搜索框](https://github.com/Vadaski/Flutter-Notebook/tree/master/mecury_project/example/beaytiful_search_bar_demo) - [TextField的焦点及动作](https://github.com/OpenFlutter/Flutter-Notebook/blob/master/mecury_project/example/textfields_focus_demo) - [微信九宫格效果](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/warp_demo) - [标签控件 chip系列](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/chip_demo) - [可展开控件 expansion系列](https://github.com/OpenFlutter/Flutter-Notebook/blob/master/mecury_project/example/expansion_demo) - [可滑动控件Sliver系列](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/sliver_demo) - [使用贝塞尔二阶曲线切割图像](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/clipper_demo) - [用户可以通过拖动以交互方式重新排序的项目的列表](https://github.com/OpenFlutter/Flutter-Notebook/blob/master/mecury_project/example/reorderble_listview_demo/) #### 功能 - [返回上一页时弹出提示信息](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/will_pop_scope_demo) - [应用开启进入闪屏页](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/splash_screen_demo) - [上拉加载,下拉刷新](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/pull_on_loading) - [json自动反序列化](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/flutter_auto_json_parsing) - [左滑删除ListView中Item](https://github.com/Vadaski/Flutter-Notebook/blob/master/mecury_project/example/swipe_to_dismiss) - [右滑返回上一页](https://github.com/Vadaski/Flutter-Notebook/tree/master/mecury_project/example/right_back_demo) - [在flutter中截屏](https://github.com/Vadaski/Flutter-Notebook/tree/master/mecury_project/example/widget_to_image) - [轻量级操作提示控件toolstip](https://github.com/OpenFlutter/Flutter-Notebook/blob/master/mecury_project/example/tool_tips_demo) - [可拖动组件draggable](https://github.com/OpenFlutter/Flutter-Notebook/blob/master/mecury_project/example/draggable_demo/) - [去掉点击事件的水波纹效果](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/without_splash_color) - [在当前页面上覆盖新的组件overlay](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/overlay) - [在不同页面传递事件EventBus](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/event_bus_demo) #### 动画 - [基本动画样例](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/animation_demo) - [神奇的Hero动画](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/hero_demo) - [AnimatedContainer](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/animated_container) - [AnimatedCrossFade](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/animated_cross_fade) - [Ripple路由转换动画](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/ripple_animation) ### 优秀第三方库 - [Awesome Flutter Packages](https://github.com/leisim/awesome-flutter-packages) - [图表库——google charts📈](https://github.com/google/charts) - [闲鱼混合栈管理框架——flutter_boost](https://github.com/alibaba/flutter_boost) - [Agora RTC SDKs 音视频通话](https://github.com/AgoraIO/Flutter-SDK) - [应用介绍页——slider](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/slider_screen) - [应用介绍页——intro_view](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/intro_views) - [从本地相册选取多张图片](https://github.com/Vadaski/Flutter-Notebook/blob/master/mecury_project/example/load_multi_image) - [使用url_launcher唤醒功能](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/url_launcher_demo) - [拿捏图片放大缩小](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/pinch_zoom_image_demo) - [一个很棒的等待动画库——Spinkit](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/spinkit_animation) ### 状态管理 - [Scoped_Model](https://github.com/Vadaski/Vadaski-flutter_note_book/tree/master/mecury_project/example/scoped_demo) - [Redux](https://github.com/Vadaski/Flutter-Notebook/tree/master/mecury_project/example/redux_demo) - [BLoC](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/bloc_demo) - [BLoC Provider模式](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/bloc_provider_pattern) - [Google-Provide](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/flutter_provide) - [fish-redux](https://github.com/alibaba/fish-redux) - [Provider](https://github.com/OpenFlutter/Flutter-Notebook/blob/master/mecury_project/example/provider_example) ### 其他 - [flutter 菜鸟 APP,包含常用 flutter 组件的中文文档与 demo 演示](https://github.com/alibaba/flutter-common-widgets-app) - [flutter widget of the week 每周介绍一个widget,轻松学习flutter](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/flutter_widget_of_the_week) - [GDD2018最新Flutter preview2 widget体验](https://github.com/Vadaski/Flutter-Notebook/tree/master/mecury_project/example/release_preview2) - [Flutter Challenge](https://github.com/OpenFlutter/Flutter-Notebook/tree/master/mecury_project/example/animation_challenge)【持续更新中】 - [一个漂亮的flutter组件库](https://github.com/samarthagarwal/FlutterScreens) - [使用flutter实现超过100个精美的ui页面](https://github.com/nb312/flutter-ui-nice) - [flutter应用收集 MADE BY THE FLUTTER社区](https://itsallwidgets.com/) - [HistoryOfEverything ———— flutter live上展示的精美应用现已开源](https://github.com/2d-inc/HistoryOfEverything) ### 书 - [Flutter in Action](https://github.com/flutterchina/flutter-in-action)
flutter_app
## 运行截图 ### 基本控件(Widget)及一些自定义控件(Widget) |||| | :--: | :--: | :--: | |[首页](https://github.com/shichunlei/flutter_app/blob/master/lib/home_page.dart)|侧边栏|版本信息| |||| |[随机诗词](https://github.com/shichunlei/flutter_app/blob/master/lib/page/random_poetry_page.dart)|[二维码(生成/扫描)](https://github.com/shichunlei/flutter_app/blob/master/lib/widget/qr_image_wiget.dart)|[设备信息](https://github.com/shichunlei/flutter_app/blob/master/lib/page/device_info_page.dart)| |||| |[瀑布流](https://github.com/shichunlei/flutter_app/blob/master/lib/widget/staggered_view_page.dart)|[评分效果](https://github.com/shichunlei/flutter_app/blob/master/lib/widget/star_rating_widget.dart)|[多边形控件](https://github.com/shichunlei/flutter_app/blob/master/lib/widget/rounded_letter_widget.dart)| |||| |[LikeButton](https://github.com/shichunlei/flutter_app/blob/master/lib/page/like_button_page.dart)|[Chip](https://github.com/shichunlei/flutter_app/blob/master/lib/widget/chip_widget.dart)|[侧滑删除](https://github.com/shichunlei/flutter_app/blob/master/lib/page/swiper_sample.dart)| |||| |Icon|Stepper|AppBar| |||| |仿探探|BottomSheet|TextField| |||| |CurvedNavigationBar|FancyBottomNavigation|BubbleBottomBar| |||| |DropDownMenu|路由过度动画|Wave| || | :--: | |TimeLine| ### [Rounded Letter](https://github.com/jhomlala/roundedletter) |||| | :--: | :--: | :--: | ### [登录注册](https://github.com/LXD312569496/flutter-learing/tree/master/login_demo) ||| | :--: | :--: | |登录|注册| ||||| | :--: | :--: | :--: | :--: | |密码登录|快速登录|注册|找回密码| ### [豆瓣电影](https://github.com/Mayandev/morec) |||| | :--: | :--: | :--: | |豆瓣电影首页(banner、热映)|豆瓣电影首页(即将上映、榜单)|豆瓣电影首页(分类浏览)| |||| |电影(正在热播)|电影(TOP250)|电影(排行榜)| |||| |电影详情1|电影详情2|电影详情3| |||| |电影花絮|电影花絮(全屏)|电影剧照| ### 天气 |||| | :--: | :--: | :--: | |实况天气/空气质量指数|逐小时、7天天气预报|生活指数| |||| |日出日落|城市列表|[仿京东地址选择器](https://github.com/shichunlei/flutter_jd_address_selector)| #### [百姓生活](https://github.com/shenghy/flutter_shop) |||| | :--: | :--: | :--: | |首页|首页|首页| |||| |分类|购物车|会员中心| |||| |商品简介|详情|评论| |||| |收货地址|地址|新增地址| ### [每日一文](https://github.com/chengww5217/one_article) |||| | :--: | :--: | :--: | |每日一文|每日一文|收藏| ### 仿微信朋友圈布局 ||||| | :--: | :--: | :--: | :--: | |头部|九宫格|选择照片|发表编辑| ### [句子迷](https://www.juzimi.com/) ### [好奇心日报](http://www.qdaily.com/) ||||| | :--: | :--: | :--: | :--: | |启动页|首页1|首页2|首页3| ||||| |Labs|我说/焦点小组|投票|你猜/你谁啊| ||||| |菜单1|菜单2|栏目列表|栏目详情| ||||| |分类列表(设计)|新闻详情1|新闻详情2|评论| ### [Flutter i18n 实现国际化](https://github.com/shichunlei/flutter_app/wiki/Flutter-i18n-%E5%AE%9E%E7%8E%B0%E5%9B%BD%E9%99%85%E5%8C%96) ## 使用到的第三方插件 | Plugin | 地址 | 版本号 | | :--: | :--: | :--: | | 网络请求 | [dio](https://pub.dartlang.org/packages/dio) |  | | 下拉刷新,上拉加载 |[flutter_easyrefresh](https://github.com/xuelongqy/flutter_easyrefresh)|| | Shared Preferences |[shared_preferences](https://github.com/flutter/plugins/tree/master/packages/shared_preferences)|| | 中国城市选择器 |[city_picker](https://github.com/CaiJingLong/flutter_city_picker)|| | 设备信息 |[device_info](https://github.com/flutter/plugins/tree/master/packages/device_info)|| | 图片选择器 | [image_picker](https://github.com/flutter/plugins/tree/master/packages/image_picker) |  | | url_launcher | [url_launcher](https://github.com/flutter/plugins/tree/master/packages/url_launcher) |  | | 视频播放器 | [video_player](https://github.com/flutter/plugins/tree/master/packages/video_player) |  | | Flutter WebView Plugin | [flutter_webview_plugin](https://github.com/fluttercommunity/flutter_webview_plugin) |  | | PackageInfo | [package_info](https://github.com/flutter/plugins/tree/master/packages/package_info) |  | | 系统分享 | [share](https://github.com/flutter/plugins/tree/master/packages/share) |  | | 引导页 | [intro-slider](https://github.com/duytq94/flutter-intro-slider) | 2.2.2 | | 评分控件 | [smooth_star_rating](https://github.com/thangmam/smoothratingbar) | 1.0.1 | | PhotoView | [photo_view](https://github.com/renancaraujo/photo_view) |  | | 时间轴 | [Timeline](https://github.com/furkantektas/timeline_list) |  | | Rounded Letter | [roundedletter](https://github.com/jhomlala/roundedletter) |  | | 数据库 | [sqflite](https://github.com/tekartik/sqflite) | 1.1.5 | | Flutter Multi Image Picker | [Flutter Multi Image Picker](https://github.com/Sh1d0w/multi_image_picker) |  | | Flutter Range Slider | [range_slider](https://github.com/boeledi/RangeSlider) | 1.2.0 | | 侧滑菜单 | [flutter_inner_drawer](https://github.com/Dn-a/flutter_inner_drawer) |  | | 字母索引、悬停 | [azlistview](https://github.com/flutterchina/azlistview) |  | | 状态管理 | [provide](https://github.com/google/flutter-provide) | 1.0.2 | | 图表 | [fl_chart](https://github.com/imaNNeoFighT/fl_chart) |  | | Badges for Flutter | [badges](https://github.com/yadaniyil/flutter_badges) |  | | Palette Generator | [palette_generator](https://github.com/flutter/packages/tree/master/packages/palette_generator) |  | | 仿京东地址选择器 | [flutter_jd_address_selector](https://github.com/shichunlei/flutter_jd_address_selector) | 0.0.1 |
《Flutter 实战》
开源地址
Flutter平台适配
另外有一个小技巧,就是你想看什么方向技术的时候,果断用 awesome + 关键词 搜索。<br>
Kotlin vs Flutter,我到底应该怎么选?
Weex
鸿蒙系统
方舟
架构
RESTful
RESTful 架构详解
【Restful】三分钟彻底了解Restful最佳实践
子主题
注解与依赖
注解
@Override
@Deprecated
@SuppressWarnings
@SafeVarargs
@SafeVarargs
元注解
@Targe
@Inherited
@Documented
@Retention
@Repeatable
注解定义使用
依赖注入的原理
Andoid
AIDL
Android:学习AIDL,这一篇文章就够了(上)
Binder
写给 Android 应用工程师的 Binder 原理剖析
Android Bander设计与实现 - 设计篇
Binder简介
国际化
权限管理
运行时权限使用
``` implementation 'com.github.dfqin:grantor:2.5' PermissionsUtil.requestPermission(getApplication(), new PermissionListener() { @Override public void permissionGranted(@NonNull String[] permissions) { Toast.makeText(DeviceListActivity.this, "用户已授权", Toast.LENGTH_LONG).show(); } @Override public void permissionDenied(@NonNull String[] permissions) { Toast.makeText(DeviceListActivity.this, "用户已拒绝", Toast.LENGTH_LONG).show(); } } , Manifest.permission.ACCESS_COARSE_LOCATION , Manifest.permission.BLUETOOTH , Manifest.permission.BLUETOOTH_ADMIN ); ```
UI
布局
关于ConstraintLayout的部分属性总结
Android中RelativeLayout和LinearLayout性能分析
ConstraintLayout UI性能分析(劣势)
解析ConstraintLayout的性能优势(优势)
标签布局
FlowLayout
FlowTagLayout
View
Android View绘制和显示原理简介
部分继承关系
View
ViewGroup
FrameLayout
DatePicker
TimePicker
CalendarView
LinearLayout
Tablelayout
RadioGroup
RelativeLayout
TextView
EditText
不弹出输入法
Button
CompoundButton
CheckBox
RadioButton
CheckedTextView
AnalogClock
ProgressBar
AbsSeekBar
RatingBar
SeekBar
ImageView
ImageButton
QuickContactBadge
SurfaceView
VideoView
Android应用程序与SurfaceFlinger服务的关系概述和学习计划
Resource
UI 事件传递
Android-UI事件传递就是这么个事儿
Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
动画
Android属性动画深入分析
组件使用
RecyclerView
博客讲解
[RecyclerView 使用完全解析 体验艺术般的控件](https://blog.csdn.net/lmj623565791/article/details/45059587)
视频讲解
[明日之星-RecyclerView](https://www.imooc.com/learn/424) [不一样的RecyclerView优雅实现复杂列表布局](https://www.imooc.com/learn/731)
自动滑动到底部
``` mRecyclerView.scrollToPosition(adapter.getItemCount()-1); ```
WebView
https://chrome//inspect
与JS交互
上传图片(base64)到H5(JS)
``` /** * 部分低端机可能会因为字符串太长而不能直接传base64 * 需要把base64封装到JSON对象中 * * @param base64JSONObject 包含base64的JSON对象 */ public void sendPhoto(WebView webView, JSONObject base64JSONObject) { webView.loadUrl("javascript:" + methodName + "(" + base64JSONObject + ")"); } ```
约定一:调用H5中js方法传递参数统一采用jsonObject对象
调用JS代码
JS调用java代码
Spinner
使用
``` <Spinner android:id="@+id/spinner1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:entries="@array/languages" /> <string-array name="languages"> <item>c语言</item> <item>java </item> <item>php</item> <item>xml</item> <item>html</item> </string-array> Spinner spinner = (Spinner) findViewById(R.id.spinner1); spinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { String[] languages = getResources().getStringArray(R.array.languages); Toast.makeText(MainActivity.this, "你点击的是:"+languages[pos], 2000).show(); } @Override public void onNothingSelected(AdapterView<?> parent) { // Another interface callback } }); ```
popupwindow
底部弹出+背景半透明
ConstraintLayout
https://blog.csdn.net/guolin_blog/article/details/53122387
LinearLayout设置透明度
Dialog
DatePickerDialog
https://www.jianshu.com/p/f5e2ae44f25b
Toast
字体大小
``` private void showToastWithShort(final String msg) { getActivity().runOnUiThread(() -> { if (mToast == null) { mToast = Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT); } LinearLayout linearLayout = (LinearLayout) mToast.getView(); TextView messageTextView = (TextView) linearLayout.getChildAt(0); messageTextView.setTextSize(35); mToast.setText(msg); mToast.show(); }); } ```
自定义界面
浮窗
gitHub
https://github.com/lichong951/camera
shape
shape绘制边框
基本使用
多级列表结构
https://github.com/WelliJohn/MultiLevelRecyclerView
https://github.com/SuperZhouyong/AdapterDemo
camera
CameraX
相册选择
``` /** * 从相册选择原生的照片(不裁切) */ private void selectFromGallery() { // TODO Auto-generatedmethod stub Intentintent=new Intent(); intent.setAction(Intent.ACTION_PICK);//Pick an item fromthe data intent.setType("image/*");//从所有图片中进行选择 startActivityForResult(intent, SELECT_ORIGINAL_PIC); } private void checkSelectOriginalPic(int requestCode, int resultCode, Intent data) { if (resultCode != Activity.RESULT_OK || requestCode != SELECT_ORIGINAL_PIC ) return; Uri selectedImage = data.getData(); //获取系统返回的照片的Uri String[] filePathColumn = { MediaStore.Images.Media.DATA }; Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);//从系统表中查询指定Uri对应的照片 cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(filePathColumn[0]); String picturePath = cursor.getString(columnIndex); //获取照片路径 cursor.close(); showLocalPhoto(picturePath); commitPhoto(picturePath); } ``` [Android开发之从相册选择照片](https://blog.csdn.net/fengyuzhengfan/article/details/40782313)
通信
HTTP
HTTP状态码100-500+详解
HTTP中的Host字段
Socket
Bluetooth
NFC
USB
Wifi
串口通信
串口工具
开源串口工具项目
串口项目
串口调试工具
大端小端解析格式
切换大小端续
``` /** * 切换大小端续 */ public static byte[] changeBytes(byte[] a){ byte[] b = new byte[a.length]; for (int i = 0; i < b.length; i++) { b[i] = a[b.length - i - 1]; } return b; } ```
java异或校检
``` /** 获取指令异或值 * @param datas * @return */ public static int getXOR(byte[] datas) { int temp = datas[1]; // 此处首位取1是因为本协议中第一个数据不参数异或校验,转为int防止结果出现溢出变成负数 for (int i = 2; i < datas.length; i++) { int preTemp = temp; int iData; if (datas[i] < 0) { iData = datas[i] & 0xff; // 变为正数计算 } else { iData = datas[i]; } if (temp < 0) { temp = temp & 0xff; // 变为正数 } temp ^= iData; System.out.println(preTemp + "异或" + iData + "=" + temp); } return temp; } ```
性能调优工具
Java 如何有效地避免OOM:善于利用软引用和弱引用
Android内存优化(一)DVM和ART原理初探
内存异常
infer
虚拟机
Dalvik虚拟机进程和线程的创建过程分析
数据持久化
SqlLite
File
SharedPreferences
保活
Android进程保活的一般套路
NDK
并发
你真的了解volatile关键字吗?
Android中的多进程模式-开启多进程模式
《Android开发艺术探索》 -- AsyncTask 工作原理
Android 多线程之IntentService 完全详解
Android 多线程之HandlerThread 完全详解
Hanler系列
Android源码解析Handler系列
Handler专辑
Android中为什么主线程不会因为Looper.loop()里的死循环卡死?
多媒体
音频
[Android中实现多段wav音频文件拼接](https://www.jianshu.com/p/86edb2422b21)
AndroidManifest
Fragment
Intent
Context
四大组件
Activity
android跳转到另一个Activity三种方法
我打赌你一定没搞明白的Activity启动模式
启动模式理解
Service
关于Android Service真正的完全详解,你需要知道的一切
BroadcastReceiver
ContentProvider
AndroidSdk
基础依赖库
``` dependencies { api fileTree(include: ['*.jar'], dir: 'libs') testImplementation 'junit:junit:4.12' androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', { exclude group: 'com.android.support', module: 'support-annotations' }) // Android support api "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion" api "com.android.support:design:$rootProject.supportLibraryVersion" api "com.android.support:percent:$rootProject.supportLibraryVersion" api "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion" api 'com.android.support.constraint:constraint-layout:1.1.2' // Retrofit api 'com.squareup.retrofit2:retrofit:2.3.0' api 'com.squareup.retrofit2:converter-gson:2.3.0' api 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' api 'com.squareup.okhttp3:logging-interceptor:3.9.1' // RxJava api 'io.reactivex.rxjava2:rxjava:2.1.9' api 'io.reactivex.rxjava2:rxandroid:2.0.2' api 'com.jakewharton.rxbinding2:rxbinding:2.1.1' api 'com.uber.autodispose:autodispose:0.8.0' api 'com.uber.autodispose:autodispose-android-archcomponents:0.8.0' // Glide api 'com.github.bumptech.glide:glide:4.7.1' api 'jp.wasabeef:glide-transformations:3.3.0' // If you want to use the GPU Filters api 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1' //Butterknife api 'com.jakewharton:butterknife:8.8.1' //内存泄漏leakcanary testImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4' debugApi 'com.squareup.leakcanary:leakcanary-android:1.5.4' releaseApi 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4' //fragmentation api 'me.yokeyword:fragmentation:1.3.5' //BaseRecyclerViewAdapterHelper api 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.38' //SwitchButton api 'com.kyleduo.switchbutton:library:1.4.6' //PhotoView api 'com.bm.photoview:library:1.4.1' api 'com.cocosw:bottomsheet:1.3.0@aar' //permissions api 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar' api 'com.yanzhenjie.alertdialog:alertdialog:1.0.1' //Bugly api 'com.tencent.bugly:crashreport:2.6.6' api files('libs/nineoldandroids-2.4.0.jar') api files('libs/commons-codec-1.3.jar') api files('libs/commons-lang-2.4.jar') //popupwindow库 api 'com.github.razerdp:BasePopup:1.9.2' //recyclerView分割线库 api 'com.arjinmc.android:recyclerviewdecoration:2.4' api 'com.jackandphantom.android:blurimage:1.2.0' //郭霖的数据库 api 'org.litepal.android:core:2.0.0' //侧滑删除 api 'com.github.anzaizai:EasySwipeMenuLayout:1.1.2' //webview api 'com.just.agentweb:agentweb:4.0.2' //事件总线eventbus api 'org.greenrobot:eventbus:3.1.1' //状态切换库 api 'com.github.Bakumon:StatusLayoutManager:1.0.1' api 'com.gyf.immersionbar:immersionbar:2.3.2-beta01' //应用内更新库 api 'com.qianwen:update-app:3.5.2' api 'com.lzy.net:okgo:3.0.4' api 'com.qianwen:okhttp-utils:3.8.0' //刷新加载库 api 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-12' //仿照iOS实现点击非输入框区域 软键盘隐藏 一款使用超简单的轻量级库 api 'com.yinglan.keyboard:hidekeyboard:1.1.3' //Android属性动画库 api 'com.daimajia.easing:library:2.0@aar' api 'com.daimajia.androidanimations:library:2.3@aar' //图文混排的textview库 api 'com.github.iwgang:simplifyspan:2.1' // api 'me.immortalz:transitionhelper:2.3.4' api 'com.github.bumptech.glide:okhttp3-integration:4.6.1' api 'com.github.promeg:tinypinyin:2.0.3' api 'com.blankj:utilcode:1.18.1' api 'cn.bingoogolapple:bga-qrcode-zxing:1.2.5' api 'com.github.lygttpod:SuperTextView:2.1.7' //动画库 api 'com.airbnb.android:lottie:2.5.4' } api 'com.jakewharton:butterknife:8.8.1' api 'me.yokeyword:fragmentation:1.3.5' api 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.38' 轮播图用'com.youth.banner:banner:1.4.10', ```
Manifest merger failed : Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91<br> is also present at [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 value=(androidx.core.app.CoreComponentFactory).<br> Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at AndroidManifest.xml:36:5-364:19 to override.
多版本迁移解决
LeakCanary
源码
UI功能特效
探照灯
二维码
定制化开发二维码扫描界面
资源 [https://github.com/luqihua/L-Qrcore](https://github.com/luqihua/L-Qrcore) 参考: [https://www.imooc.com/article/20971](https://www.imooc.com/article/20971)
推荐使用https://github.com/journeyapps/zxing-android-embedded
填空题View特效
啡常OK
Excel电子表格
ZzExcelCreator
GitHub
逆向
因一纸设计稿,我把竞品APP扒得裤衩不剩(上)
构建异常
Execution failed for task ':app:mergeDebugJavaResource'. > A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade > More than one file was found with OS independent path 'META-INF/DEPENDENCIES'<br>
``` packagingOptions { exclude 'META-INF/DEPENDENCIES' exclude 'META-INF/NOTICE' exclude 'META-INF/LICENSE' exclude 'META-INF/LICENSE.txt' exclude 'META-INF/NOTICE.txt' } ```
系统签名
1,在应用程序的AndroidManifest.xml中的manifest节点中加入 android:sharedUserId="android.uid.system"这个属性。 2, java -Xmx2048m -jar signapk.jar -w testkey.x509.pem testkey.pk8 input.apk output.apk 或者 java -jar signapk.jar platform.x509.pem platform.pk8 input.apk output.apk 或者改造签名文件
Benchmark
google benchmark主要是对c++中的函数进行基准功能测试。
版本更新框架
XUpdate
AndroidStudio
插件集
常用21款插件
Genymotion
virtualBox
Genymotion
快捷键
https://mp.weixin.qq.com/s/eMrBP72V9D7oaVlmaTym8g
ERROR: Unable to resolve dependency for
Android Tools
查找
https://mp.weixin.qq.com/s/_pXtKCW60bIeZFxW8FKdXA
异常情况
mac Android studio com.intellij.ide.plugins.PluginManager$StartupAbortedExceptiir
仔细查看错误信息 本次是由于插件 Code Iris导致的。关闭此插件重启解决
AS Debug还能这么玩?我也是服
ADB
adb通过wifi连接android设备
查询分辨率
adb shell wm size
adb命令集合
android面试资料
android_interviews
随机数
小程序
小程序注册
搭建环境
调试Helloworld
代码结构
配置文件
json
project.config.json
app.json
pages:页面
tabBar
页面结构
VIEW
button
页面样式
页面交互
事件机制项
tap
catchtap
冒泡策略
事件绑定
bindtap
云开发
云函数
云数据库
数据类型
String:字符
Number:数字
Object:对象
Array:数组
Bool:布尔
GeoPoint:地理位置点
Date:日期时间
子主题
云存储
上传文件
文件下载
第三方组件库
分页加载
UI框架
vant
mpx
图片轮播
组件
camera
全屏预览
``` <camera class ="camera" device-position="back" flash="off" binderror="error" style="width: 100%; height: 100vh;"> </camera> ```
预览帧回调
``` onLoad() { this.ctx = wx.createCameraContext() const l = this.ctx.onCameraFrame((frame)=>{ console.log(frame) }) listener.start({ success: function(){ console.log('listener start') }, fail: function(){ console.log('listener fail') } ```
预览帧参数解析
参数
arrayBuffer
参数值是RGBA值
转换为base64
``` let pngData = upng.encode([res.data.buffer], res.width, res.height) // 4. base64编码 let base64 = wx.arrayBufferToBase64(pngData) ```
首先进行png||jpg处理
然后进行base64转换
下载upng.js和piko.mini.js
[下载地址](https://download.csdn.net/download/weixin_38023551/10513997 )
arrayBuffer转换为可识别图片base64
开发工具
Git
Gradle
版本自增
``` def releaseTime() { return new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC")) } def gitVersionCode() { def cmd = 'git rev-list HEAD --first-parent --count' cmd.execute().text.trim().toInteger() } def gitVersionTag() { def cmd = 'git describe --tags' def version = cmd.execute().text.trim() def pattern = "-(\\d+)-g" def matcher = version =~ pattern if (matcher) { version = version.substring(0, matcher.start()) + "." + matcher[0][1] } else { version = version + "" } return version } ```
Gradle User Guide 中文版
[学习地址](https://mp.weixin.qq.com/s/TVuF8_304DZQ1wbe1vm1ag)
Tasks
构建异常
SSL peer shut down incorrectly
jenkins
APK加固
[360加固](http://blog.tomlezen.com/2018/04/12/dev-360-jiagu-gradle-plugin/) [Android使用jenkins全自动构建打包-Windows版本(Android,Jenkins,360加固,Email,QRcode,参数构建,蒲公英)](https://www.cnblogs.com/pmokj/p/9809241.html) []()
蒲公英
接口测试
https://www.eolinker.com/
JSON Quick Format
同屏工具
vysor
scrcpy
win
linux
mac
友盟
工具类IO
CL编程指南
热修复
简称 "DoKit" 。一款功能齐全的客户端( iOS 、Android、微信小程序 )研发助手,你值得拥有。
子主题
vcn--mac同屏工具
[Mac 自带的 VNC 客户端](https://blog.csdn.net/youshaoduo/article/details/82698355) [Mac OS X开始VNC](https://jingyan.baidu.com/article/92255446487820851648f4d6.html)
单元测试
Android
Android单元测试 - 几个重要问题
gradlew test
``` android { ... testOptions.unitTests.all { testLogging { events 'passed', 'skipped', 'failed', 'standardOut', 'standardError' outputs.upToDateWhen { false } showStandardStreams = true } } } ```
test
Context#getString(int)的测试用例
``` import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class MockUnitTest { private static final String FAKE_STRING = "AndroidUnitTest"; @Mock Context mMockContext; @Test public void readStringFromContext_LocalizedString() { //模拟方法调用的返回值,隔离对Android系统的依赖 when(mMockContext.getString(R.string.app_name)).thenReturn(FAKE_STRING); assertThat(mMockContext.getString(R.string.app_name), is(FAKE_STRING)); when(mMockContext.getPackageName()).thenReturn("com.jdqm.androidunittest"); System.out.println(mMockContext.getPackageName()); } } ```
SHaredPreference
``` @RunWith(RobolectricTestRunner.class) @Config(application = RoboApp.class) public class SharedPreferenceDaoTest { public static final String TEST_KEY = "instrumentedTest"; public static final String TEST_STRING = "玉刚说"; SharedPreferenceDao spDao; @Before public void setUp() { //这里的Context采用RuntimeEnvironment.application来替代应用的Context spDao = new SharedPreferenceDao(RuntimeEnvironment.application); } @Test public void sharedPreferenceDaoWriteRead() { spDao.put(TEST_KEY, TEST_STRING); Assert.assertEquals(TEST_STRING, spDao.get(TEST_KEY)); } } ```
隔离native方法
``` public class ModelTest { Model model; @Before public void setUp() throws Exception { model = mock(Model.class); } @Test public void testNativeMethod() throws Exception { when(model.nativeMethod()).thenReturn(true); Assert.assertTrue(model.nativeMethod()); } } ````
在内部new,不方便Mock
``` public class Presenter { Model model; public Presenter() { model = new Model(); } public boolean getBoolean() { return model.getBoolean()); } } ``` ``` public class Presenter { Model model; public Presenter(Model model) { this.model = model; } public boolean getBoolean() { return model.getBoolean(); } } ``` ``` public class PresenterTest { Model model; Presenter presenter; @Before public void setUp() throws Exception { // mock Model对象 model = mock(Model.class); presenter = new Presenter(model); } @Test public void testGetBoolean() throws Exception { when(model.getBoolean()).thenReturn(true); Assert.assertTrue(presenter.getBoolean()); } } ```
本地单元测试-文件操作
``` //注意包名保持一致 package android.os; public class Environment { public static File getExternalStorageDirectory() { return new File("本地文件系统目录"); } } ``` ``` public class FileDaoTest { public static final String TEST_STRING = "Hello Android Unit Test."; FileDao fileDao; @Before public void setUp() throws Exception { fileDao = new FileDao(); } @Test public void testWrite() throws Exception { String name = "readme.md"; fileDao.write(name, TEST_STRING); String content = fileDao.read(name); Assert.assertEquals(TEST_STRING, content); } } ````
Androidtest
SharedPreference的实现
``` public class SharedPreferenceDao { private SharedPreferences sp; public SharedPreferenceDao(SharedPreferences sp) { this.sp = sp; } public SharedPreferenceDao(Context context) { this(context.getSharedPreferences("config", Context.MODE_PRIVATE)); } public void put(String key, String value) { SharedPreferences.Editor editor = sp.edit(); editor.putString(key, value); editor.apply(); } public String get(String key) { return sp.getString(key, null); } } ``` ``` // @RunWith 只在混合使用 JUnit3 和 JUnit4 需要,若只使用JUnit4,可省略 @RunWith(AndroidJUnit4.class) public class SharedPreferenceDaoTest { public static final String TEST_KEY = "instrumentedTest"; public static final String TEST_STRING = "玉刚说"; SharedPreferenceDao spDao; @Before public void setUp() { spDao = new SharedPreferenceDao(App.getContext()); } @Test public void sharedPreferenceDaoWriteRead() { spDao.put(TEST_KEY, TEST_STRING); Assert.assertEquals(TEST_STRING, spDao.get(TEST_KEY)); } } ```
UI测试
Espresso
UI Automator
压力测试
Monkey
配方一
// Robolectric<br> testImplementation 'org.robolectric:robolectric:4.3'<br> testImplementation "org.robolectric:shadows-multidex:4.3"<br>// androidx<br> androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'<br> // Core library<br> androidTestImplementation 'androidx.test:core:1.0.0'<br><br> // AndroidJUnitRunner and JUnit Rules<br> androidTestImplementation 'androidx.test:runner:1.1.0'<br> androidTestImplementation 'androidx.test:rules:1.1.0'<br><br> // Assertions<br> androidTestImplementation 'androidx.test.ext:junit:1.0.0'<br> androidTestImplementation 'androidx.test.ext:truth:1.0.0'<br> androidTestImplementation 'com.google.truth:truth:0.42'<br><br> // Espresso dependencies<br> androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'<br> androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.0'<br> androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0'<br> androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.1.0'<br> androidTestImplementation 'androidx.test.espresso:espresso-web:3.1.0'<br> androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.1.0'
// PowerMock brings in the mockito dependency<br> testCompile 'org.powermock:powermock-module-junit4:1.6.5'<br> testCompile 'org.powermock:powermock-module-junit4-rule:1.6.5'<br> testCompile 'org.powermock:powermock-api-mockito:1.6.5'<br> testCompile 'org.powermock:powermock-classloading-xstream:1.6.5'
Junit
@Test
@Test(expected = ParseException.class)
建议使用下面规则测试异常 @Rule <br>publicExpectedException expectedEx = ExpectedException.none(); <br> <br>@Test <br>publicvoid passwordIsEmptyThrowsException() throwsInvalidPasswordException { <br> expectedEx.expect(InvalidPasswordException.class); <br> expectedEx.expectMessage("required"); <br> Password.validate(""); <br>}
Mocktio
testImplementation 'org.mockito:mockito-core:2.19.0'<br>
例子
``` import static org.hamcrest.core.Is.is; import static org.junit.Assert.*; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.*; import static org.mockito.internal.verification.VerificationModeFactory.atLeast; @RunWith(MockitoJUnitRunner.class) public class MyClassTest { @Mock MyClass test; @Test public void mockitoTestExample() throws Exception { //可是使用注解@Mock替代 //MyClass test = mock(MyClass.class); // 当调用test.getUniqueId()的时候返回43 when(test.getUniqueId()).thenReturn(18); // 当调用test.compareTo()传入任意的Int值都返回43 when(test.compareTo(anyInt())).thenReturn(18); // 当调用test.close()的时候,抛NullPointerException异常 doThrow(new NullPointerException()).when(test).close(); // 当调用test.execute()的时候,什么都不做 doNothing().when(test).execute(); assertThat(test.getUniqueId(), is(18)); // 验证是否调用了1次test.getUniqueId() verify(test, times(1)).getUniqueId(); // 验证是否没有调用过test.getUniqueId() verify(test, never()).getUniqueId(); // 验证是否至少调用过2次test.getUniqueId() verify(test, atLeast(2)).getUniqueId(); // 验证是否最多调用过3次test.getUniqueId() verify(test, atMost(3)).getUniqueId(); // 验证是否这样调用过:test.query("test string") verify(test).query("test string"); // 通过Mockito.spy() 封装List对象并返回将其mock的spy对象 List list = new LinkedList(); List spy = spy(list); //指定spy.get(0)返回"Jdqm" doReturn("Jdqm").when(spy).get(0); assertEquals("Jdqm", spy.get(0)); } } ```
使用说明
powermock
testImplementation 'org.powermock:powermock-api-mockito2:1.7.4'<br> testImplementation 'org.powermock:powermock-module-junit4:1.7.4'<br>
例子
``` @RunWith(PowerMockRunner.class) @PrepareForTest({StaticClass1.class, StaticClass2.class}) public class StaticMockTest { @Test public void testSomething() throws Exception{ // mock完静态类以后,默认所有的方法都不做任何事情 mockStatic(StaticClass1.class); when(StaticClass1.getStaticMethod()).thenReturn("Jdqm"); StaticClass1.getStaticMethod(); //验证是否StaticClass1.getStaticMethod()这个方法被调用了一次 verifyStatic(StaticClass1.class, times(1)); } } ```
Robolectric
testImplementation "org.robolectric:robolectric:3.8"<br><br>android {<br> ...<br> testOptions {<br> unitTests {<br> includeAndroidResources = true<br> }<br> }<br>}<br>
例子
``` public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final TextView tvResult = findViewById(R.id.tvResult); Button button = findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { tvResult.setText("Robolectric Rocks!"); } }); } } ```
https://blog.csdn.net/shensky711/article/details/53561172
https://www.jianshu.com/p/c6d91b8a491f
异常情况
Caused by: java.lang.UnsupportedOperationException: XML file /Users/lichong/Documents/com.glodon/code/GateFaceAndroid/app/build/intermediates/merged-not-compiled-resources/debug/layout/glodon_launch_activity.xml line #-1 (sorry, not yet implemented): You must supply a layout_height attribute.
android.content.res.Resources$NotFoundException: Resource ID #0x7f060054
``` testOptions { unitTests { includeAndroidResources = true } } ```
Caused by: java.lang.UnsupportedOperationException: Binary XML file line #10: You must supply a layout_height attribute.
和demin有关系
https://github.com/robolectric/robolectric/issues/1769
java.lang.RuntimeException: Method setLocale in android.content.res.Configuration not mocked. See http://g.co/androidstudio/not-mocked for details.
``` [Robolectric] WARN: Android SDK 10000 requires Java 9 (have Java 8). Tests won't be run on SDK 10000 unless explicitly requested. [Robolectric] com.glodon.glm.gateface.activity.BaseActivityTest.showToast: sdk=22; resources=BINARY java.lang.RuntimeException: Method clear in android.util.SparseArray not mocked. See http://g.co/androidstudio/not-mocked for details. at android.util.SparseArray.clear(SparseArray.java) at org.robolectric.shadows.ShadowAccessibilityNodeInfo.resetObtainedInstances(ShadowAccessibilityNodeInfo.java:280) at org.robolectric.Shadows.reset(Shadows.java:2129) at org.robolectric.android.internal.AndroidTestEnvironment.resetState(AndroidTestEnvironment.java:486) at org.robolectric.RobolectricTestRunner.lambda$finallyAfterTest$0(RobolectricTestRunner.java:334) at org.robolectric.util.PerfStatsCollector.measure(PerfStatsCollector.java:75) at org.robolectric.RobolectricTestRunner.finallyAfterTest(RobolectricTestRunner.java:332) at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:261) at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) java.lang.RuntimeException: Method setLocale in android.content.res.Configuration not mocked. See http://g.co/androidstudio/not-mocked for details. at android.content.res.Configuration.setLocale(Configuration.java) at org.robolectric.android.DeviceConfig.setLocale(DeviceConfig.java:388) at org.robolectric.android.DeviceConfig.applyRules(DeviceConfig.java:256) at org.robolectric.android.Bootstrap.applyQualifiers(Bootstrap.java:50) at org.robolectric.android.internal.AndroidTestEnvironment.setUpApplicationState(AndroidTestEnvironment.java:151) at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:301) at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:243) at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) 解决: targetSdkVersion 28 ```
java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.
@RunWith(RobolectricTestRunner.class)
@RunWith(RobolectricTestRunner.class)
java.lang.Exception: Main looper has queued unexecuted runnables. This might be the cause of the test failure. You might need a shadowOf(getMainLooper()).idle() call.
@LooperMode(LooperMode.Mode.PAUSED)<br>
TextView
ImageVIew
``` ImageView splashIv=activity.findViewById(R.id.iv_splash); Assert.assertNotNull(splashIv); int drawableResId = Shadows.shadowOf(splashIv.getDrawable()).getCreatedFromResId(); Assert.assertEquals(R.mipmap.splash_logo,drawableResId); ```
https://stackoverflow.com/questions/18008044/assert-imageview-was-loaded-with-specific-drawable-resource-id
``` ImageView imageView = activity.findViewById(R.id.real_whitelist_setting_back); Assert.assertEquals(R.drawable.ic_launcher_background, Shadows.shadowOf(imageView.getBackground()).getCreatedFromResId()); ```
AndroidX Test
测试结构
JUnit4+Mockito+PowerMockito+Robolectric
安全
手机功能
资源网站
图标
[矢量图](https://www.easyicon.net/iconsearch/android/)
https://www.iconfont.cn/search/index?q=movie
玩Android
beJson
亿级流量大型网站
慕课视频网
热修复
制图
RemixIcon
菜鸟教程Kotlin
ss免费账号