summary icon indicating copy to clipboard operation
summary copied to clipboard

my blog

Results 64 summary issues
Sort by recently updated
recently updated
newest added

在这里断断续续写了一些学习记录,后面我将不在这里更新了,掘金的书写体验会更好一点。以后我将会成体系的分享一些自己学习,工作中的总结, 也欢迎关注 https://juejin.cn/user/3835551075551021

再来看一下图片选择器相关的UI开发,顺便梳理一下UI相关的知识点。常用的一些基础东西就不写了,这里只记录一些容易弄混,出错,不容易记住的东西 假设我们想要做成的图片选择器的UI类似于下图这样: ![[email protected]][1] ### 主题 我们希望UI上的元素尽可能的可配置,因此将相关的UI属性抽出来并定义成主题。比如:标题的颜色,文字的颜色,字体等。在开发的时候,还是像知乎那样提供两套基础的主题。一种主题的样式显示效果如上图所示,采用白底的头部。另一种,我们采用蓝底的头部。先回顾一下`Style` 和 `Theme` 相关的基础。新增`Style`和`Theme`的方式是一样的,都是直接在xml文件的``结点中添加``结点,定义名称,添加属性。那么`Style`和`Theme`的区别是什么, Google官方是这么说的: > What's the difference between a style and a theme? * A style applies to a View. In XML, you...

最近因为工作上的需要看了一些网上开源的图片选择器,有大厂如知乎出品的`Matisse`, 也有一些个人开发者写的。看完后发现,因为这个功能是和具体的产品设计风格相关,所以网上的图片选择器很多情况下是不能满足我们的实际项目开发。比如UI设计差距较大,有的图片选择器不支持预览网络图片,不支持全屏(沉浸式导航)。所以我们的做法通常是参考网上的一个图片选择器,然后再自己根据产品设计修改相应UI,添加一些新的功能。有时候因为项目的进度原因,部份代码都没有仔细看。刚好最近有打算梳理一下自己的Android体系结构的想法,就想着自己重写一个图片选择器,借此来梳理一下相关的知识点。 这里想要实现的图片选择器具体的需求我就不列出来了,直接脑补,或者看最终的成品。这里先来列举一下这个功能所需要的知识点 ## 数据相关: * 如何从Android系统中查询所有的相册 * 如何查询某个相册中的所有图片,并排序 * 如何将最新拍摄的照片插入到系统的图库中,然后查出来再显示。 * 选中的照片的存储 ## UI显示相关: * 相册列表的显示 * 每个相册中图片的显示 * 选中相册后图片列表需要对应的刷新 * 大图的预览 * 图片的选择与取消选择 * 沉浸式导航 ## 其它 *...

## 一次关于SingleTask的填坑 这个milestone客户那边做了一个功能,在做这个功能的时候,那边的开发把我们app中的activity的launchmode给改了。之前我们都是采用standard模式的,整个app中维持着一个activity,每次跳屏前会将当前的activity finish掉。下次再进到这个屏,重新执行onCreate,创建这个activity。同时我们有很多初始化UI和数据的代码写在`onCreate`方法中。现在因为修改了activity的launchmode,导致了每次进到一个屏时,其activity的`onCreate`方法不一定执行。从而引起了一堆的UI和数据不一致的问题。 在谈到这些问题之前,我们先来自一下activity的launchmode。都知道activity的启动模式有四种,Google推荐我们尽量不要去修改activity的launchmode,对于大多数的应用standard模式就可以适用。这里我们只讲singleTask这一个launchmode. ### 例子 假设有四个activity。如果采用默认的launchmode, 依次启动 A->B->C->D。栈中将会保留这四个Activity,如果再由D启动A,A启动B, 则栈中顺序会是A->B->C->D->A->B。 这个很好理解。 如果我把B的launchmode 改为singleTask. 依次启动A->B->C->D。栈中仍会保留这四个activity,如果再由D启动A,会发现栈中有5个activity. 采用`adb shell dump sys activity`命令,我们可以查看当前activity和栈的情况: > Running activities (most recent first): > TaskRecord{423f84e0 #81 A=com.example.fredye.myapplication...

#### 起因 上周大家都安静的等待着release,美国客户那边突然要求我们在项目的这个milestone里把`certificate pinning`加进去。按道理来说,在release前几天不应该再加这种effort比较大的task。后来知道,是因为那边公司的上层要视察,强烈要求。看来`领导视察`这种活动是普遍存在啊,美国也不例外。没办法,客户就是上帝,我们就硬着头皮做task,连续加班熬夜搞了两晚上。在此,小总结一下。 在我们上网的时候,如果涉及到支付相关的操作,比如说在网上用支付宝买东西,你会发现地址栏中的URL是以`https`开头的;用Google的很多产品也会发现URL是以`https`开头;访问本网页,同样,URL也是采用`https`开头。这是因为这些服务提供商为了保证用户数据的安全性采用的一种措施。`HTTPS`可以理解是加密了的`HTTP`请求,在传输过程中会对数据进行加密。现在当你访问一些正规的网站时,若URL是以`HTTPS`开头的,很多浏览器的地址栏会有一个绿色的锁的标识,表示当前的访问是安全的。如下图: ![image](https://cloud.githubusercontent.com/assets/6369935/3812048/3a5c675e-1ca6-11e4-965a-fc1021785af5.png) ### SSL 与 HTTPS `SSL(Secure Sockets Layer 安全套接层)`是为网络通信提供安全及数据完整性的一种安全协议。需要注意一点是,它是在传输层对网络连接进行加密。SSL协议的优势在于它是与应用层协议独立无关的。高层的应用层协议(例如:HTTP、FTP、Telnet等等)能透明的建立于SSL协议之上。SSL协议在应用层协议通信之前就已经完成加密算法、通信密钥的协商以及服务器认证工作。在此之后应用层协议所传送的数据都会被加密,从而保证通信的私密性。`SSL协议`是基于非对称加密算法的。关于`非对称加密`,稍后会讲到。 `HTTPS(Hypertext Transfer Protocol Secure)安全超文本传输协议`是一个属于应用层的协议,`HTTPS`是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,`HTTPS`的安全基础是SSL。 **非对称加密** 了解非对称加密之前先了解一下对称加密。简单来讲,对称加密的算法的加密和解密都是采用同一个密钥。如数据A,通过使用密钥B,加密成为密文C。任何人,只要获得了密钥B,就能够对截获的密文C解密,还原出源数据A。 而非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 ### HTTPS通信流程 1,客户端向服务端发出请求,服务端将公钥(以及服务端证书)响应给客户端; 2,客户端接收到服务器端端公钥与证书,验证证书是否在信任域内,不信任则结束通信,信任则使用服务端传过来的公钥生成一个"预备主密码",返回给服务端。 3,服务端接收客户端传过来的"预备主密码"密文,使用私钥解密。非对称加密的安全性也就在于此了,第三方无法获取到"预备主密码"的明文,因为除了服务端,其他任何人是没有私钥的。 4,双方使用"预备主密码"生成用于会话的"主密码"。确认后,结束本次握手,停止使用非对称加密。 5,双方使用"主密码"对称加密传输数据,直到本次会话结束。 **需要注意的** 1...

这篇文章来自于我的[博客](http://www.fredye.cn), 后面会慢慢的把东西整理整理移到博客上去。 每个函数都有一个`prototype`属性,该属性指向一个对象。而该属性只有在该函数做为构造器时才会发生作用,当函数作为构造器时,通过new去创建对象, 对象的原型(内置的prototype属性)会指向构造器(函数)的prototype属性。对象会自动拥有这个对象的构造函数的prototype的成员属性和方法. 先看一个示例: ``` function P () { } typeof P.prototype; //"object" //prototype指向的是一个对象 ``` 我们来修改P的`prototype`属性. ``` var protoObj = { date: new Date(), say: function() { console.log('Hello World');...

## 采用AES算法对Android程序中的数据进行加密存储 在开发android程序时,难免会在本地存储一些数据,对于一些敏感数据,我们需要对其进行加密存储,下面记录一下我们采用的一个加密算法。 首先了解一下Android中的四种存储方式。 ## 四种存储方式 ### 1 SharedPreference SharedPreference中的数据是以key-value的集合需要保存,有些类似于java中的`Hashtable`。只是SharedPreference中只能存储一些简单的数据类型。同一个Application中可以指定多个sharedPreference,也可以只使用同一个sharedPreference文件。 > getSharedPreferences(String name, int mode)方法是根据第一个参数名来区分sharedPreference文件。 > getPreferences(int mode) 是返回系统默认的sharedPreference文件。 不管采用哪种方式,sharedPreference存在手机中的位子是在`/data/data/{packagename}/shared_prefs/`目录下。 ### 2 Internal Storage Internal Storage(内部存储)并不是将数据存在内存中,内部存储在手机中的位子是`/data/data/{packagename}files/`,内部存储中的文件只能被自己的应用访问到。当一个应用卸载之后,内部存储中的这些文件也被删除。 获取内部存储的路径可以用 > ``` java...

### Gradle和 Gradle Wrapper 在使用Gradle前我们是不需要安装Gradle的。此时我们需要借助Gradle Wraper, Gradle Wrapper的工作方式是先通过脚本来判断需要Gradle版本是否安装,如果没有则会先去下载对应版本的Gradle。该脚本对应的linux版本是`gradlew`, windows版本是`gradlew.bat` ### Gradle的安装 如果想在终端中使用Gradle,我们需要手动去安装Gradle ```shell unzip ~/Downloads/gradle-3.3-all.zip -d /usr/local/gradle/ &&\ echo '# Adding Gradle to system path export GRADLE_HOME=/usr/local/gradle/gradle-3.3 PATH=$GRADLE_HOME/bin:$PATH export PATH'...

在Activity的整个生命周期中,Activity只有三种稳定状态: Resumed, Paused, Stopped. Resumed状态下,Activity是处于和用户交互状态。Paused状态下,Activity是部份遮盖,此时不会响应用户的行为。不会执行任何代码(不代表后台线程不执行). Stopped 状态,Activity对用户不可见,不会执行任何代码。 #### 创建一个新的Activity 其生命周期回调方法的执行顺序是: onCreate—>onStart()—>onResume() 实际上 activity 在onStart()方法被调用后就已是对用户可见。只是在onResume()执行完后才能和用户交互。 #### Activity的销毁 系统通常是在执行了onPause() 和onStop() 之后再调用onDestory(),除非你的程序在onCreate()方法里面就调用了finish()方法。比如在Splash屏,我们会在onCreate()方法里面调用finish()方法,这样系统会直接就调用onDestory()方法,其它生命周期方法则都不会执行(onPause(), onStop()). #### Activity的暂停 当activity被其它的组件挡住,如Dialog,导致其部分可见且不能和用户交互,此时activity将会进入paused状态。在onPause()方法中,我们应该进行资源的释放操作(停止动画)。当activity处于暂停状态时, Activity 实例是驻留在内存中的。 从paused状态恢复到可交互状态 会调用onResume()方法。 #### Activity 的停止和重启...

#最近因为各种机缘接触到了`WeakReference`,今天在此总结一下。 Java中将对象的引用分为`强引用`、`软引用`、`弱引用`和`虚引用`这四种级别,从而使程序能更加灵活的控制对象的生命周期。先简单介绍一下四种引用: > - **强引用**:平时我们编程的时候例如:Object object=new Object();那object就是一个强引用了。如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内存空 间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。 > - **软引用(SoftReference)**:如果一个对象只具有软引用,那就类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。 软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。 > - **弱引用(WeakReference)**::如果一个对象只具有弱引用,那就类似于可有可物的生活用品。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它 所管辖的内存区域的过程中,**一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。**不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。 弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。 > - **虚引用(PhantomReference)**:`虚引用`顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。 虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。为一个对象设置虚引用关联的叭一目的就是能在这个对象被收集器回收时收到一个系统通知。 ### 弱引用(WeakReference) 一个简单的弱引用的例子,从中我们可以看到`WeakReference`的基本使用。 ``` Java public...