Skip to content

Commit 9889887

Browse files
committed
update
1 parent 0e23acc commit 9889887

8 files changed

+40
-28
lines changed

AdavancedPart/Android6.0权限系统.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
103103
为了能找到用户可能需要说明的情况,`android`提供了一个工具类方法`ActivityCompat.shouldShowRequestPermissionRationale().`。如果应用之前申请了该权限但是用户拒绝授权后该方法会返回`true`。(在Android 6.0之前调用的时候会直接返回false)
104104

105105
> 注意:如果用户之前拒绝了权限申请并且选择了请求权限对话框中的`Don’t ask again`选项,该方法就会返回`false`。如果设备策略禁止了该应用使用该权限,该方法也会返回`false`。(我测试的时候发现请求权限的对话框中并没有`Don’t asdk again`这一项)
106-
> ![image](https://raw.githubusercontent.com/CharonChui/Pictures/master/request_permission_dialog.png?raw=true)
106+
107+
<img src="https://raw.githubusercontent.com/CharonChui/Pictures/master/request_permission_dialog.png?raw=true" width="100%" height="100%">
107108

108109
##### 申请需要的权限
109110

AdavancedPart/Android启动模式详解.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
Android启动模式详解
22
===
33

4-
- standard
5-
默认模式。在该模式下,`Activity`可以拥有多个实例,并且这些实例既可以位于同一个task,也可以位于不同的task。每次都会新创建。
6-
- singleTop
4+
- `standard`
5+
默认模式。在该模式下,`Activity`可以拥有多个实例,并且这些实例既可以位于同一个`task`,也可以位于不同的`task`。每次都会新创建。
6+
- `singleTop`
77
该模式下,在同一个`task`中,如果存在该`Activity`的实例,并且该`Activity`实例位于栈顶则不会创建该`Activity`的示例,而仅仅只是调用`Activity``onNewIntent()`。否则的话,则新建该`Activity`的实例,并将其置于栈顶。
8-
- singleTask
8+
- `singleTask`
99
顾名思义,只容许有一个包含该`Activity`实例的`task`存在!
1010
`android`浏览器`browser`中,`BrowserActivity``launcherMode="singleTask"`,因为`browser`不断地启动自己,所以要求这个栈中保持只能有一个自己的实例,`browser`上网的时候,
1111
遇到播放视频的链接,就会通过隐式`intent`方式跳转找`Gallery3D`中的`MovieView`这个类来播放视频,这时候如果你点击`home`键,再点击`browser`,你会发现`MovieView`这个类已经销毁不存在了,
@@ -16,19 +16,19 @@ Android启动模式详解
1616
以`singleTask`方式启动的`Activity`,全局只有唯一个实例存在,因此,当我们第一次启动这个`Activity`时,系统便会创建一个新的任务栈,并且初始化一个`Activity`实例,放在新任务栈的底部,如果下次再启动这个`Activity`时,
1717
系统发现已经存在这样的`Activity`实例,就会调用这个`Activity`实例的`onNewIntent`方法,从而把它激活起来。从这句话就可以推断出,以`singleTask`方式启动的`Activity`总是属于一个任务栈的根`Activity`。
1818
下面我们看一下示例图: 
19-
![image](https://github.com/CharonChui/Pictures/blob/master/singletask.gif?raw=true)
19+
![image](https://github.com/CharonChui/Pictures/blob/master/singletask.gif?raw=true)
2020
坑爹啊!有木有!前面刚说`singleTask`会在新的任务中运行,并且位于任务堆栈的底部,这里在`Task B`中,一个赤裸裸的带着`singleTask`标签的箭头无情地指向`Task B`堆栈顶端的`Activity Y`,什么鬼?
2121
这其实是和`taskAffinity`有关,在将要启动时,系统会根据要启动的`Activity``taskAffinity`属性值在系统中查找这样的一个`Task``Task``affinity`属性值与即将要启动的`Activity``taskAffinity`属性值一致。如果存在,
2222
就返回这个`Task`堆栈顶端的`Activity`回去,不重新创建任务栈了,再去启动另外一个`singletask``activity`时就会在跟它有相同`taskAffinity`的任务中启动,并且位于这个任务的堆栈顶端,于是,前面那个图中,
2323
就会出现一个带着`singleTask`标签的箭头指向一个任务堆栈顶端的`Activity Y`了。在上面的`AndroidManifest.xml`文件中,没有配置`MainActivity``SubActivity``taskAffinity`属性,
2424
于是它们的`taskAffinity`属性值就默认为父标签`application``taskAffinity`属性值,这里,标签`application``taskAffinity`也没有配置,于是它们就默认为包名。
25-
总的来说:`singleTask`的结论与`android:taskAffinity`相关  
25+
总的来说:`singleTask`的结论与`android:taskAffinity`相关:   
2626
- 设置了`singleTask`启动模式的`Activity`,它在启动的时候,会先在系统中查找属性值`affinity`等于它的属性值`taskAffinity`的任务栈的存在;如果存在这样的任务栈,它就会在这个任务栈中启动,否则就会在新任务栈中启动。
2727
因此,如果我们想要设置了`singleTask`启动模式的`Activity`在新的任务栈中启动,就要为它设置一个独立的`taskAffinity`属性值。以`A`启动`B`来说当`A``B``taskAffinity`相同时:第一次创建`B`的实例时,并不会启动新的`task`
2828
而是直接将`B`添加到`A`所在的`task`;否则,将`B`所在`task`中位于`B`之上的全部`Activity`都删除,然后跳转到`B`中。
2929
- 如果设置了`singleTask`启动模式的`Activity`不是在新的任务中启动时,它会在已有的任务中查看是否已经存在相应的`Activity`实例,如果存在,就会把位于这个`Activity`实例上面的`Activity`全部结束掉,
3030
即最终这个Activity实例会位于任务的堆栈顶端中。以`A`启动`B`来说,当`A``B``taskAffinity`不同时:第一次创建`B`的实例时,会启动新的`task`,然后将`B`添加到新建的`task`中;否则,将`B`所在`task`中位于`B`之上的全部`Activity`都删除,然后跳转到`B`中。
31-
- singleInstance
31+
- `singleInstance`
3232
顾名思义,是单一实例的意思,即任意时刻只允许存在唯一的`Activity`实例,而且该`Activity`所在的`task`不能容纳除该`Activity`之外的其他`Activity`实例!
3333
它与`singleTask`有相同之处,也有不同之处。
3434
相同之处:任意时刻,最多只允许存在一个实例。

AdavancedPart/ApplicationId vs PackageName.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ android {
5252
...
5353
```
5454

55-
像之前一样,你需要在`Manifest`文件中指定你在代码中使用的'package name',像上面`AndroidManifest.xml`的例子。
55+
像之前一样,你需要在`Manifest`文件中指定你在代码中使用的`package name`,像上面`AndroidManifest.xml`的例子。
5656
下面进入关键部分了:当你按照上面的方式做完后,这两个包就是相互独立的了。你现在可以很简单的重构你的代码-通过修改`Manifest`中的包名来修改在你的`activitise``services`中使用的包和在重构你在代码中的引用声明。这不会影响你应用的最终`id`,也就是在`Gradle`文件中的`applicationId`
5757

5858
你可以通过以下`Gradle DSL`方法为应用的`flavors``build types`指定不同的`applicationId`:

ArchitectureComponents/1.简介(一).md

+7-5
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212

1313
通用的框架准则官方建议在架构`App`的时候遵循以下两个准则:
1414

15-
- 关注分离
15+
- 关注分离
16+
1617
其中早期开发`App`最常见的做法是在`Activity`或者`Fragment`中写了大量的逻辑代码,导致`Activity``Fragment`中的代码很臃肿,十分不易维护。现在很多`App` 开发者都注意到了这个问题,所以前两年`MVP`结构就非常有市场,目前普及率也很高。
1718

18-
- 模型驱动UI
19+
- 模型驱动`UI`
20+
1921
模型持久化的好处就是:即使系统回收了`App`的资源用户也不会丢失数据,而且在网络不稳定的情况下`App`依然可以正常地运行。从而保证了`App`的用户体验。
2022

2123

@@ -28,10 +30,10 @@
2830
> A collection of libraries that help you design robust, testable, and maintainable apps. Start with classes for managing your UI component lifecycle and handling data persistence.
2931
3032

31-
`Android Architecture Components`,简称`AAC`意思就是一个处理`UI`的生命周期 与数据的持久化更加牛逼的架构
33+
`Android Architecture Components`,简称`AAC`意思就是一个处理`UI`的生命周期 与数据的持久化的架构
3234

33-
- 一个全新的库集合,可帮助您设计强大,可测试和可维护的应用程序。用于管理UI组件生命周期和处理数据持久性
34-
- 便捷管理App的声明周期:新的生命周期感知(`lifecycle-aware`)组件可帮助您管理`Activity``Fragment`的生命周期。存储配置改变,避免内存泄漏,并使用`LiveData``ViewModel``LifecycleObserver``LifecycleOwner`轻松将数据加载到UI中。
35+
- 一个全新的库集合,可帮助您设计强大,可测试和可维护的应用程序。用于管理`UI`组件生命周期和处理数据持久性
36+
- 便捷管理`App`的声明周期:新的生命周期感知(`lifecycle-aware`)组件可帮助您管理`Activity``Fragment`的生命周期。存储配置改变,避免内存泄漏,并使用`LiveData``ViewModel``LifecycleObserver``LifecycleOwner`轻松将数据加载到UI中。
3537
- `Room`:一个`SQLite`对象映射库
3638

3739

ArchitectureComponents/5.ViewModel(五).md

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
5.ViewModel(五)
22
===
33

4-
ViewModel是用来存储UI层的数据,以及管理对应的数据,当数据修改的时候,可以马上刷新UI
4+
`ViewModel`是用来存储`UI`层的数据,以及管理对应的数据,当数据修改的时候,可以马上刷新`UI`
55

6-
Android系统提供控件,比如Activity和Fragment,这些控件都是具有生命周期方法,这些生命周期方法被系统调用。
6+
`Android`系统提供控件,比如`Activity``Fragment`,这些控件都是具有生命周期方法,这些生命周期方法被系统调用。
77

8-
当这些控件被销毁或者被重建的时候,如果数据保存在这些对象中,那么数据就会丢失。比如在一个界面,保存了一些用户信息,当界面重新创建的时候,就需要重新去获取数据。当然了也可以使用控件自动再带的方法,在onSaveInstanceState方法中保存数据,在onCreate中重新获得数据,但这仅仅在数据量比较小的情况下。如果数据量很大,这种方法就不能适用了。
8+
当这些控件被销毁或者被重建的时候,如果数据保存在这些对象中,那么数据就会丢失。比如在一个界面,保存了一些用户信息,当界面重新创建的时候,就需要重新去获取数据。当然了也可以使用控件自动再带的方法,`onSaveInstanceState`方法中保存数据,在`onCreate`中重新获得数据,但这仅仅在数据量比较小的情况下。如果数据量很大,这种方法就不能适用了。
99

10-
另外一个问题就是,经常需要在Activity中加载数据,这些数据可能是异步的,因为获取数据需要花费很长的时间。那么Activity就需要管理这些数据调用,否则很有可能会产生内存泄露问题。最后需要做很多额外的操作,来保证程序的正常运行。
10+
另外一个问题就是,经常需要在`Activity`中加载数据,这些数据可能是异步的,因为获取数据需要花费很长的时间。那么`Activity`就需要管理这些数据调用,否则很有可能会产生内存泄露问题。最后需要做很多额外的操作,来保证程序的正常运行。
1111

12-
同时Activity不仅仅只是用来加载数据的,还要加载其他资源,做其他的操作,最后Activity类变大,就是我们常讲的上帝类。也有不少架构是把一些操作放到单独的类中,比如MVP就是这样,创建相同类似于生命周期的函数做代理,这样可以减少Activity的代码量,但是这样就会变得很复杂,同时也难以测试。
12+
同时`Activity`不仅仅只是用来加载数据的,还要加载其他资源,做其他的操作,最后`Activity`类变大,就是我们常讲的上帝类。也有不少架构是把一些操作放到单独的类中,比如`MVP`就是这样,创建相同类似于生命周期的函数做代理,这样可以减少`Activity`的代码量,但是这样就会变得很复杂,同时也难以测试。
1313

14-
AAC中提供ViewModel可以很方便的用来管理数据。我们可以利用它来管理UI组件与数据的绑定关系。ViewModel提供自动绑定的形式,当数据源有更新的时候,可以自动立即的更新UI。
14+
`AAC`中提供`ViewModel`可以很方便的用来管理数据。我们可以利用它来管理`UI`组件与数据的绑定关系。`ViewModel`提供自动绑定的形式,当数据源有更新的时候,可以自动立即的更新`UI`
1515

1616

17-
实现ViewModel
17+
实现`ViewModel`
1818
---
1919

2020
```java

BasicKnowledge/Android动画.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Android动画
5656
contentView.startAnimation(set); // 播放一组动画.
5757
```
5858

59-
6. Frame动画
59+
6. Frame动画
6060
在`SDK`中提到,不要在`onCreate`中调用`start`方法开始播放`Frame`动画,因为`AnimationDrawable`还没有完全跟`Window`相关联,如果想要界面显示时就开始播放帧动画的话,可以在`onWindowFocusChanged()`中调用`start()`。
6161

6262
- 在`drawable`目录下新建一个`xml`文件,内容如下:
@@ -198,7 +198,7 @@ public class FloatEvaluator implements TypeEvaluator {
198198
`evaluate()`方法当中传入了三个参数,第一个参数`fraction`非常重要,这个参数用于表示动画的完成度的,我们应该根据它来计算当前动画的值应该是多少,第二第三个参数分别表示动画的初始值和结束值。那么上述代码的逻辑就比较清晰了,用结束值减去初始值,算出它们之间的差值,然后乘以`fraction`这个系数,再加上初始值,那么就得到当前动画的值了。
199199

200200

201-
###`TimeInterplator`
201+
### `TimeInterplator`
202202
Time interplator定义了属性值变化的方式,如线性均匀改变,开始慢然后逐渐快等。在Property Animation中是TimeInterplator,在View Animation中是Interplator,这两个是一样的,在3.0之前只有Interplator,3.0之后实现代码转移至了TimeInterplator。Interplator继承自TimeInterplator,内部没有任何其他代码。
203203

204204
- AccelerateInterpolator      加速,开始时慢中间加速
@@ -223,11 +223,11 @@ ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
223223
```
224224

225225
### `ViewPropertyAnimator`
226-
227-
`* <p>This class is not constructed by the caller, but rather by the View whose properties
226+
```
227+
* <p>This class is not constructed by the caller, but rather by the View whose properties
228228
* it will animate. Calls to {@link android.view.View#animate()} will return a reference
229-
* to the appropriate ViewPropertyAnimator object for that View.</p>`
230-
229+
* to the appropriate ViewPropertyAnimator object for that View.</p>
230+
```
231231
如果需要对一个View的多个属性进行动画可以用ViewPropertyAnimator类,该类对多属性动画进行了优化,会合并一些invalidate()来减少刷新视图,该类在3.1中引入。
232232

233233
`view.animate()`方法会返回`ViewPropertyAnimator`类。

BasicKnowledge/资源文件拷贝的三种方式.md

+9
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@
2323
答案就是把`assets`目录移`src/main`下面就可以了?为什么呢?因为我们打开`app.impl`可以看到`<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />`。
2424
所以把`assets`移到`src/main/`下就可以了。
2525

26+
`Raw``Assets`两者有什么区别呢?
27+
28+
- 两者目录下的文件在打包后会原封不动的保存在`apk`包中,不会被编译成二进制。
29+
- 在读取这两个资源文件夹中的文件时会有一定的限制,即单个文件大小不能超过`1M` ,如果读取超过1M的文件会报`Data exceeds UNCOMPRESS_DATA_MAX (1314625 vs 1048576)``IOException`
30+
- `raw`中的文件会被映射到`R`文件中,访问的时候直接使用资源`ID``assets`文件夹下的文件不会被映射到`R`文件中。
31+
- `raw`不可以有目录结构,而`assets`则可以有目录结构,也就是`assets`目录下可以再建立文件夹。
32+
33+
34+
2635
---
2736

2837
- 邮箱 :charon.chui@gmail.com

JavaKnowledge/volatile和Synchronized区别.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ volatile和Synchronized区别
1212
使用建议:在两个或者更多的线程访问的成员变量上使用`volatile`。当要访问的变量已在`synchronized`代码块中,或者为常量时,不必使用。
1313
由于使用`volatile`屏蔽掉了`JVM`中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。 就跟`C`中的一样 禁止编译器进行优化.
1414

15-
注意:如果给一个变量加上volatile修饰符,就相当于:每一个线程中一旦这个值发生了变化就马上刷新回主存,使得各个线程取出的值相同。编译器不要对这个变量的读、写操作做优化。但是值得注意的是,除了对`long`和`double`的简单操作之外,`volatile`并不能提供原子性。
15+
注意:如果给一个变量加上`volatile`修饰符,就相当于:每一个线程中一旦这个值发生了变化就马上刷新回主存,使得各个线程取出的值相同。编译器不要对这个变量的读、写操作做优化。但是值得注意的是,除了对`long``double`的简单操作之外,`volatile`并不能提供原子性。
1616
所以,就算你将一个变量修饰为`volatile`,但是对这个变量的操作并不是原子的,在并发环境下,还是不能避免错误的发生!
1717

1818
- synchronized

0 commit comments

Comments
 (0)