Skip to content

Commit 5b08650

Browse files
authored
Merge pull request LRH1993#23 from Notzuonotdied/master
调整了Java并发和Java虚拟机中的编辑细节
2 parents 67ea65a + c2270c6 commit 5b08650

16 files changed

+952
-778
lines changed

android/basis/ContentProvider.md

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ content://com.example.app.provider/table/#
5252

5353
### 4.2 MIME数据类型
5454

55+
- 解释:MIME:全称Multipurpose Internet Mail Extensions,多功能Internet 邮件扩充服务。它是一种多用途网际邮件扩充协议,在1992年最早应用于电子邮件系统,但后来也应用到浏览器。MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
5556
- 作用:指定某个扩展名的文件用某种应用程序来打开
5657
如指定`.html`文件采用`text`应用程序打开、指定`.pdf`文件采用`flash`应用程序打开
5758
- 具体使用:
@@ -241,40 +242,40 @@ long personid = ContentUris.parseId(uri);
241242
### 4.6 UriMatcher类
242243

243244
- 作用
244-
1.`ContentProvider` 中注册`URI`
245+
1.`ContentProvider` 中注册`URI`
245246
2. 根据 `URI` 匹配 `ContentProvider` 中对应的数据表
246247
- 具体使用
247248

248249
```Java
249250
// 步骤1:初始化UriMatcher对象
250-
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
251-
//常量UriMatcher.NO_MATCH = 不匹配任何路径的返回码
252-
// 即初始化时不匹配任何东西
251+
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
252+
//常量UriMatcher.NO_MATCH = 不匹配任何路径的返回码
253+
// 即初始化时不匹配任何东西
253254

254255
// 步骤2:在ContentProvider 中注册URI(addURI())
255-
int URI_CODE_a = 1
256-
int URI_CODE_b = 2
257-
matcher.addURI("cn.scu.myprovider", "user1", URI_CODE_a);
258-
matcher.addURI("cn.scu.myprovider", "user2", URI_CODE_b);
259-
// 若URI资源路径 = content://cn.scu.myprovider/user1 ,则返回注册码URI_CODE_a
260-
// 若URI资源路径 = content://cn.scu.myprovider/user2 ,则返回注册码URI_CODE_b
256+
int URI_CODE_a = 1
257+
int URI_CODE_b = 2
258+
matcher.addURI("cn.scu.myprovider", "user1", URI_CODE_a);
259+
matcher.addURI("cn.scu.myprovider", "user2", URI_CODE_b);
260+
// 若URI资源路径 = content://cn.scu.myprovider/user1 ,则返回注册码URI_CODE_a
261+
// 若URI资源路径 = content://cn.scu.myprovider/user2 ,则返回注册码URI_CODE_b
261262

262263
// 步骤3:根据URI 匹配 URI_CODE,从而匹配ContentProvider中相应的资源(match())
263264

264-
@Override
265-
public String getType(Uri uri) {
266-
Uri uri = Uri.parse(" content://cn.scu.myprovider/user1");
265+
@Override
266+
public String getType (Uri uri){
267+
Uri uri = Uri.parse(" content://cn.scu.myprovider/user1");
267268

268-
switch(matcher.match(uri)){
269-
// 根据URI匹配的返回码是URI_CODE_a
270-
// 即matcher.match(uri) == URI_CODE_a
271-
case URI_CODE_a:
272-
return tableNameUser1;
269+
switch (matcher.match(uri)) {
270+
// 根据URI匹配的返回码是URI_CODE_a
271+
// 即matcher.match(uri) == URI_CODE_a
272+
case URI_CODE_a:
273+
return tableNameUser1;
273274
// 如果根据URI匹配的返回码是URI_CODE_a,则返回ContentProvider中的名为tableNameUser1的表
274-
case URI_CODE_b:
275-
return tableNameUser2;
275+
case URI_CODE_b:
276+
return tableNameUser2;
276277
// 如果根据URI匹配的返回码是URI_CODE_b,则返回ContentProvider中的名为tableNameUser2的表
277-
}
278+
}
278279
}
279280
```
280281

@@ -290,21 +291,21 @@ long personid = ContentUris.parseId(uri);
290291

291292
```Java
292293
// 步骤1:注册内容观察者ContentObserver
293-
getContentResolver().registerContentObserver(uri);
294-
// 通过ContentResolver类进行注册,并指定需要观察的URI
294+
getContentResolver().registerContentObserver(uri);
295+
// 通过ContentResolver类进行注册,并指定需要观察的URI
295296

296297
// 步骤2:当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者)
297-
public class UserContentProvider extends ContentProvider {
298-
public Uri insert(Uri uri, ContentValues values) {
299-
db.insert("user", "userid", values);
300-
getContext().getContentResolver().notifyChange(uri, null);
301-
// 通知访问者
302-
}
298+
public class UserContentProvider extends ContentProvider {
299+
public Uri insert(Uri uri, ContentValues values) {
300+
db.insert("user", "userid", values);
301+
getContext().getContentResolver().notifyChange(uri, null);
302+
// 通知访问者
303+
}
303304
}
304305

305306
// 步骤3:解除观察者
306-
getContentResolver().unregisterContentObserver(uri);
307-
// 同样需要通过ContentResolver类进行解除
307+
getContentResolver().unregisterContentObserver(uri);
308+
// 同样需要通过ContentResolver类进行解除
308309
```
309310

310311
至此,关于`ContentProvider`的使用已经讲解完毕
@@ -381,10 +382,11 @@ public class MyProvider extends ContentProvider {
381382

382383
// UriMatcher类使用:在ContentProvider 中注册URI
383384
private static final UriMatcher mMatcher;
384-
static{
385+
386+
static {
385387
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
386388
// 初始化
387-
mMatcher.addURI(AUTOHORITY,"user", User_Code);
389+
mMatcher.addURI(AUTOHORITY, "user", User_Code);
388390
mMatcher.addURI(AUTOHORITY, "job", Job_Code);
389391
// 若URI资源路径 = content://cn.scu.myprovider/user ,则返回注册码User_Code
390392
// 若URI资源路径 = content://cn.scu.myprovider/job ,则返回注册码Job_Code
@@ -419,7 +421,6 @@ public class MyProvider extends ContentProvider {
419421
/**
420422
* 添加数据
421423
*/
422-
423424
@Override
424425
public Uri insert(Uri uri, ContentValues values) {
425426

@@ -438,7 +439,7 @@ public class MyProvider extends ContentProvider {
438439
// System.out.println(personid);
439440

440441
return uri;
441-
}
442+
}
442443

443444
/**
444445
* 查询数据
@@ -455,7 +456,7 @@ public class MyProvider extends ContentProvider {
455456
// System.out.println(personid);
456457

457458
// 查询数据
458-
return db.query(table,projection,selection,selectionArgs,null,null,sortOrder,null);
459+
return db.query(table, projection, selection, selectionArgs, null, null, sortOrder, null);
459460
}
460461

461462
/**
@@ -487,7 +488,7 @@ public class MyProvider extends ContentProvider {
487488
/**
488489
* 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
489490
*/
490-
private String getTableName(Uri uri){
491+
private String getTableName(Uri uri) {
491492
String tableName = null;
492493
switch (mMatcher.match(uri)) {
493494
case User_Code:
@@ -498,17 +499,16 @@ public class MyProvider extends ContentProvider {
498499
break;
499500
}
500501
return tableName;
501-
}
502502
}
503+
}
503504
```
504505

505506
**步骤3:注册 创建的 ContentProvider类**
506507
**AndroidManifest.xml**
507508

508-
```java
509+
``` xml
509510
<provider android:name="MyProvider"
510-
android:authorities="cn.scu.myprovider"
511-
/>
511+
android:authorities="cn.scu.myprovider"/>
512512
```
513513

514514
**步骤4:进程内访问 ContentProvider中的数据**

android/basis/activity.md

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ onCreate\(\)-&gt;onStart\(\)-&gt;onResume\(\)-&gt;onPause\(\)-&gt;onStop\(\)-&gt
5656

5757
在了解这种情况下的生命周期时,首先应该了解这两个回调:**onSaveInstanceState和onRestoreInstanceState**
5858

59-
在Activity由于异常情况下终止时,系统会调用onSaveInstanceState来保存当前Activity的状态。这个方法的调用是在onStop之前,它和onPause没有既定的时序关系,该方法只在Activity被异常终止的情况下调用。当异常终止的Activity被重建以后,系统会调用onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象参数同时传递给onRestoreInstanceState和onCreate方法。因此,可以通过onRestoreInstanceState方法来恢复Activity的状态,该方法的调用时机是在onStart之后。**其中onCreate和onRestoreInstanceState方法来恢复Activity的状态的区别:**onRestoreInstanceState回调则表明其中Bundle对象非空,不用加非空判断。onCreate需要非空判断。建议使用onRestoreInstanceState。
59+
在Activity由于异常情况下终止时,系统会调用onSaveInstanceState来保存当前Activity的状态。这个方法的调用是在onStop之前,它和onPause没有既定的时序关系,该方法只在Activity被异常终止的情况下调用。当异常终止的Activity被重建以后,系统会调用onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象参数同时传递给onRestoreInstanceState和onCreate方法。因此,可以通过onRestoreInstanceState方法来恢复Activity的状态,该方法的调用时机是在onStart之后。**其中onCreate和onRestoreInstanceState方法来恢复Activity的状态的区别:** onRestoreInstanceState回调则表明其中Bundle对象非空,不用加非空判断。onCreate需要非空判断。建议使用onRestoreInstanceState。
6060

6161

6262
![](http://upload-images.jianshu.io/upload_images/3985563-23d90471fa7f12d2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
@@ -145,7 +145,7 @@ Activity的管理是采用任务栈的形式,任务栈采用“后进先出”
145145

146146
**特殊情况,如果在Service或Application中启动一个Activity,其并没有所谓的任务栈,可以使用标记位Flag来解决。解决办法:为待启动的Activity指定FLAG\_ACTIVITY\_NEW\_TASK标记位,创建一个新栈。**
147147

148-
**应用场景:**绝大多数Activity。如果以这种方式启动的Activity被跨进程调用,在5.0之前新启动的Activity实例会放入发送Intent的Task的栈的顶部,尽管它们属于不同的程序,这似乎有点费解看起来也不是那么合理,所以在5.0之后,上述情景会创建一个新的Task,新启动的Activity就会放入刚创建的Task中,这样就合理的多了。
148+
**应用场景:** 绝大多数Activity。如果以这种方式启动的Activity被跨进程调用,在5.0之前新启动的Activity实例会放入发送Intent的Task的栈的顶部,尽管它们属于不同的程序,这似乎有点费解看起来也不是那么合理,所以在5.0之后,上述情景会创建一个新的Task,新启动的Activity就会放入刚创建的Task中,这样就合理的多了。
149149

150150
##### \(2\)栈顶复用模式(singleTop)
151151

@@ -164,26 +164,24 @@ Activity的管理是采用任务栈的形式,任务栈采用“后进先出”
164164

165165
![](http://upload-images.jianshu.io/upload_images/3985563-6378dae7ea249294.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
166166

167-
168-
169-
170-
171-
**应用场景:**在通知栏点击收到的通知,然后需要启动一个Activity,这个Activity就可以用singleTop,否则每次点击都会新建一个Activity。当然实际的开发过程中,测试妹纸没准给你提过这样的bug:某个场景下连续快速点击,启动了两个Activity。如果这个时候待启动的Activity使用 singleTop模式也是可以避免这个Bug的。同standard模式,如果是外部程序启动singleTop的Activity,在Android 5.0之前新创建的Activity会位于调用者的Task中,5.0及以后会放入新的Task中。
167+
**应用场景:** 在通知栏点击收到的通知,然后需要启动一个Activity,这个Activity就可以用singleTop,否则每次点击都会新建一个Activity。当然实际的开发过程中,测试妹纸没准给你提过这样的bug:某个场景下连续快速点击,启动了两个Activity。如果这个时候待启动的Activity使用 singleTop模式也是可以避免这个Bug的。同standard模式,如果是外部程序启动singleTop的Activity,在Android 5.0之前新创建的Activity会位于调用者的Task中,5.0及以后会放入新的Task中。
172168

173169
##### \(3\)栈内复用模式(singleTask)
174170

175171
该模式是一种单例模式,即一个栈内只有一个该Activity实例。该模式,可以通过在AndroidManifest文件的Activity中指定该Activity需要加载到那个栈中,即singleTask的Activity可以指定想要加载的目标栈。singleTask和taskAffinity配合使用,指定开启的Activity加入到哪个栈中。
176172

177-
```java
173+
``` xml
178174
<activity android:name=".Activity1"
179-
android:launchMode="singleTask"
180-
android:taskAffinity="com.lvr.task"
181-
android:label="@string/app_name">
175+
android:launchMode="singleTask"
176+
android:taskAffinity="com.lvr.task"
177+
android:label="@string/app_name">
182178
</activity>
183179
```
184180

185-
**关于taskAffinity的值:**每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名。
186-
**执行逻辑:**
181+
**关于taskAffinity的值:** 每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名。
182+
183+
**执行逻辑:**
184+
187185
在这种模式下,如果Activity指定的栈不存在,则创建一个栈,并把创建的Activity压入栈内。如果Activity指定的栈存在,如果其中没有该Activity实例,则会创建Activity并压入栈顶,如果其中有该Activity实例,则把该Activity实例之上的Activity杀死清除出栈,重用并让该Activity实例处在栈顶,然后调用onNewIntent\(\)方法。
188186

189187
对应如下三种情况:
@@ -205,7 +203,7 @@ Activity的管理是采用任务栈的形式,任务栈采用“后进先出”
205203

206204

207205

208-
**应用场景:**大多数App的主页。对于大部分应用,当我们在主界面点击回退按钮的时候都是退出应用,那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能报销毁。在跨应用Intent传递时,如果系统中不存在singleTask Activity的实例,那么将创建一个新的Task,然后创建SingleTask Activity的实例,将其放入新的Task中。
206+
**应用场景:** 大多数App的主页。对于大部分应用,当我们在主界面点击回退按钮的时候都是退出应用,那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能报销毁。在跨应用Intent传递时,如果系统中不存在singleTask Activity的实例,那么将创建一个新的Task,然后创建SingleTask Activity的实例,将其放入新的Task中。
209207

210208
##### \(4\)单例模式(singleInstance)
211209

@@ -218,11 +216,11 @@ Activity的管理是采用任务栈的形式,任务栈采用“后进先出”
218216

219217

220218

221-
**应用场景:**呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。建议谨慎使用。
219+
**应用场景:** 呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。建议谨慎使用。
222220

223221
### 3.特殊情况——前台栈和后台栈的交互
224222

225-
假如目前有两个任务栈。前台任务栈为AB,后台任务栈为CD,这里假设CD的启动模式均为singleTask,现在请求启动D,那么这个后台的任务栈都会被切换到前台,这个时候整个后退列表就变成了ABCD。当用户按back返回时,列表中的activity会一一出栈,如下图。
223+
假如目前有两个任务栈。前台任务栈为AB,后台任务栈为CD,这里假设CD的启动模式均为singleTask,现在请求启动D,那么这个后台的任务栈都会被切换到前台,这个时候整个后退列表就变成了ABCD。当用户按back返回时,列表中的activity会一一出栈,如下图。
226224

227225

228226
![](http://upload-images.jianshu.io/upload_images/3985563-4aeb1947bba27e44.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
@@ -246,12 +244,12 @@ Activity的管理是采用任务栈的形式,任务栈采用“后进先出”
246244

247245
Activity的Flags很多,这里介绍集中常用的,用于设定Activity的启动模式。可以在启动Activity时,通过Intent的addFlags\(\)方法设置。
248246

249-
**\(1\)FLAG\_ACTIVITY\_NEW\_TASK**
247+
**\(1\)FLAG\_ACTIVITY\_NEW\_TASK**
250248
其效果与指定Activity为singleTask模式一致。
251249

252-
**\(2\)FLAG\_ACTIVITY\_SINGLE\_TOP**
250+
**\(2\)FLAG\_ACTIVITY\_SINGLE\_TOP**
253251
其效果与指定Activity为singleTop模式一致。
254252

255-
**\(3\)FLAG\_ACTIVITY\_CLEAR\_TOP**
253+
**\(3\)FLAG\_ACTIVITY\_CLEAR\_TOP**
256254
具有此标记位的Activity,当它启动时,在同一个任务栈中所有位于它上面的Activity都要出栈。如果和singleTask模式一起出现,若被启动的Activity已经存在栈中,则清除其之上的Activity,并调用该Activity的onNewIntent方法。如果被启动的Activity采用standard模式,那么该Activity连同之上的所有Activity出栈,然后创建新的Activity实例并压入栈中。
257255

0 commit comments

Comments
 (0)