├── .gitignore
├── Android.md
├── HTTP请求和响应.xmind
├── Java.md
├── README.md
├── UML.mdj
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── nan
│ │ └── androidreview
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ └── test.html
│ ├── java
│ │ └── com
│ │ │ └── nan
│ │ │ └── androidreview
│ │ │ ├── App.java
│ │ │ ├── BitmapUtils.java
│ │ │ ├── CacheManager.java
│ │ │ ├── ConstraintLayoutActivity.java
│ │ │ ├── ExceptionDemo.java
│ │ │ ├── Fruit.java
│ │ │ ├── HandlerThreadActivity.java
│ │ │ ├── MainActivity.java
│ │ │ ├── Sample.java
│ │ │ ├── TestFragment.java
│ │ │ ├── TestIntentService.java
│ │ │ ├── TestThread.java
│ │ │ ├── TestType.java
│ │ │ ├── dagger
│ │ │ ├── Factory.java
│ │ │ ├── FactoryActivity.java
│ │ │ ├── FactoryActivityComponent.java
│ │ │ └── Product.java
│ │ │ ├── dagger_moudle
│ │ │ ├── HttpActivity.java
│ │ │ ├── HttpActivityComponent.java
│ │ │ ├── HttpActivityModule.java
│ │ │ ├── OkHttpClient.java
│ │ │ └── RetrofitManager.java
│ │ │ ├── designpattern
│ │ │ ├── abstractfactory
│ │ │ │ ├── AbstractFactory.java
│ │ │ │ ├── ConcreteProductA1.java
│ │ │ │ ├── ConcreteProductA2.java
│ │ │ │ ├── ConcreteProductB1.java
│ │ │ │ ├── ConcreteProductB2.java
│ │ │ │ ├── Factory1.java
│ │ │ │ ├── Factory2.java
│ │ │ │ ├── ProductA.java
│ │ │ │ └── ProductB.java
│ │ │ ├── adapter
│ │ │ │ ├── demo1
│ │ │ │ │ ├── Adaptee.java
│ │ │ │ │ ├── Adapter.java
│ │ │ │ │ ├── Client.java
│ │ │ │ │ ├── ConcreteTarget.java
│ │ │ │ │ └── Target.java
│ │ │ │ └── demo2
│ │ │ │ │ ├── Adaptee.java
│ │ │ │ │ ├── Adapter.java
│ │ │ │ │ ├── Client.java
│ │ │ │ │ ├── ConcreteTarget.java
│ │ │ │ │ └── Target.java
│ │ │ ├── bridge
│ │ │ │ ├── Abstraction.java
│ │ │ │ ├── Client.java
│ │ │ │ ├── ConcreteImplementor1.java
│ │ │ │ ├── ConcreteImplementor2.java
│ │ │ │ ├── Implementor.java
│ │ │ │ ├── RefineAbstraction1.java
│ │ │ │ └── RefineAbstraction2.java
│ │ │ ├── builder
│ │ │ │ └── Product.java
│ │ │ ├── chain
│ │ │ │ ├── Client.java
│ │ │ │ ├── ConcreteHandler1.java
│ │ │ │ ├── ConcreteHandler2.java
│ │ │ │ ├── ConcreteHandler3.java
│ │ │ │ ├── Handler.java
│ │ │ │ ├── Request.java
│ │ │ │ └── Response.java
│ │ │ ├── command
│ │ │ │ ├── Client.java
│ │ │ │ ├── Command.java
│ │ │ │ ├── ConcreteCommand1.java
│ │ │ │ ├── ConcreteCommand2.java
│ │ │ │ ├── ConcreteReceiver1.java
│ │ │ │ ├── ConcreteReceiver2.java
│ │ │ │ ├── Invoker.java
│ │ │ │ └── Receiver.java
│ │ │ ├── composite
│ │ │ │ ├── Client.java
│ │ │ │ ├── Component.java
│ │ │ │ ├── Composite.java
│ │ │ │ └── Leaf.java
│ │ │ ├── decorator
│ │ │ │ ├── Client.java
│ │ │ │ ├── Component.java
│ │ │ │ ├── ConcreteComponent.java
│ │ │ │ ├── ConcreteDecorator1.java
│ │ │ │ ├── ConcreteDecorator2.java
│ │ │ │ └── Decorator.java
│ │ │ ├── facade
│ │ │ │ ├── ClassA.java
│ │ │ │ ├── ClassB.java
│ │ │ │ ├── ClassC.java
│ │ │ │ └── Facade.java
│ │ │ ├── factorymethod
│ │ │ │ ├── Client.java
│ │ │ │ ├── ConcreteFactory.java
│ │ │ │ ├── ConcreteProduct1.java
│ │ │ │ ├── ConcreteProduct2.java
│ │ │ │ ├── Factory.java
│ │ │ │ └── Product.java
│ │ │ ├── flyweight
│ │ │ │ ├── Client.java
│ │ │ │ ├── ConcreteFlyweight.java
│ │ │ │ ├── Flyweight.java
│ │ │ │ └── FlyweightFactory.java
│ │ │ ├── interpreter
│ │ │ │ ├── Client.java
│ │ │ │ ├── Context.java
│ │ │ │ ├── Expression.java
│ │ │ │ ├── NonterminalExpression.java
│ │ │ │ └── TerminalExpression.java
│ │ │ ├── interpreter_demo
│ │ │ │ ├── AddExpression.java
│ │ │ │ ├── Calculator.java
│ │ │ │ ├── Client.java
│ │ │ │ ├── Expression.java
│ │ │ │ ├── SubExpression.java
│ │ │ │ ├── SymbolExpression.java
│ │ │ │ └── VarExpression.java
│ │ │ ├── iterator
│ │ │ │ ├── Aggregate.java
│ │ │ │ ├── Client.java
│ │ │ │ ├── ConcreteAggregate.java
│ │ │ │ ├── ConcreteIterator.java
│ │ │ │ └── Iterator.java
│ │ │ ├── mediator
│ │ │ │ ├── Client.java
│ │ │ │ ├── Colleague.java
│ │ │ │ ├── ConcreteColleague1.java
│ │ │ │ ├── ConcreteColleague2.java
│ │ │ │ ├── ConcreteMediator.java
│ │ │ │ └── Mediator.java
│ │ │ ├── memento
│ │ │ │ ├── Caretaker.java
│ │ │ │ ├── Client.java
│ │ │ │ ├── Memento.java
│ │ │ │ └── Originator.java
│ │ │ ├── observer
│ │ │ │ ├── Client.java
│ │ │ │ ├── ConcreteObserver.java
│ │ │ │ ├── ConcreteSubject.java
│ │ │ │ ├── Observer.java
│ │ │ │ └── Subject.java
│ │ │ ├── prototype
│ │ │ │ ├── ConcretePrototype.java
│ │ │ │ └── Prototype.java
│ │ │ ├── proxy
│ │ │ │ ├── demo1
│ │ │ │ │ ├── Client.java
│ │ │ │ │ ├── RealSubject.java
│ │ │ │ │ ├── Subject.java
│ │ │ │ │ └── SubjectProxy.java
│ │ │ │ └── demo2
│ │ │ │ │ ├── Client.java
│ │ │ │ │ ├── RealSubject.java
│ │ │ │ │ ├── Subject.java
│ │ │ │ │ └── SubjectIH.java
│ │ │ ├── singleton
│ │ │ │ ├── demo1
│ │ │ │ │ └── Singleton.java
│ │ │ │ ├── demo2
│ │ │ │ │ └── Singleton.java
│ │ │ │ ├── demo3
│ │ │ │ │ └── Singleton.java
│ │ │ │ ├── demo4
│ │ │ │ │ └── Singleton.java
│ │ │ │ ├── demo5
│ │ │ │ │ └── Singleton.java
│ │ │ │ ├── demo6
│ │ │ │ │ └── Singleton.java
│ │ │ │ └── demo7
│ │ │ │ │ └── Singleton.kt
│ │ │ ├── state
│ │ │ │ ├── Client.java
│ │ │ │ ├── ConcreteState1.java
│ │ │ │ ├── ConcreteState2.java
│ │ │ │ ├── Context.java
│ │ │ │ └── State.java
│ │ │ ├── strategy
│ │ │ │ ├── Client.java
│ │ │ │ ├── ConcreteStrategy1.java
│ │ │ │ ├── ConcreteStrategy2.java
│ │ │ │ ├── Context.java
│ │ │ │ └── Strategy.java
│ │ │ ├── templatemethod
│ │ │ │ ├── AbstractClass.java
│ │ │ │ ├── Client.java
│ │ │ │ ├── ConcreteClass1.java
│ │ │ │ └── ConcreteClass2.java
│ │ │ └── visitor
│ │ │ │ ├── Client.java
│ │ │ │ ├── ConcreteElement1.java
│ │ │ │ ├── ConcreteElement2.java
│ │ │ │ ├── ConcreteVisitor1.java
│ │ │ │ ├── ConcreteVisitor2.java
│ │ │ │ ├── Element.java
│ │ │ │ └── Visitor.java
│ │ │ ├── leak
│ │ │ ├── LeakActivity.java
│ │ │ └── Utils.java
│ │ │ └── net
│ │ │ ├── TCPClient.java
│ │ │ ├── TCPServer.java
│ │ │ ├── UDPClient.java
│ │ │ └── UDPServer.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_constraint_layout.xml
│ │ ├── activity_factory.xml
│ │ ├── activity_leak.xml
│ │ ├── activity_main.xml
│ │ └── activity_test1.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── nan
│ └── androidreview
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── lint
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── nan
│ │ └── lint
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── nan
│ │ │ └── lint
│ │ │ ├── LogUtilDetector.java
│ │ │ └── MyIssueRegistry.java
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── nan
│ └── lint
│ └── ExampleUnitTest.java
├── settings.gradle
├── 互联网协议.xmind
├── 未来计划.md
├── 浏览器输入URL之后 发生了什么.xmind
├── 计算机网络.md
├── 设计模式.mdj
└── 设计模式与架构.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 |
--------------------------------------------------------------------------------
/HTTP请求和响应.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huannan/AndroidReview/e15f26864f71f55a14148065300b2d73858135ce/HTTP请求和响应.xmind
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 大纲:
2 |
3 | * [Java](https://github.com/huannan/AndroidReview/blob/master/Java.md)
4 | * [Android](https://github.com/huannan/AndroidReview/blob/master/Android.md)
5 | * [计算机网络](https://github.com/huannan/AndroidReview/blob/master/计算机网络.md)
6 | * [算法](https://github.com/huannan/AndroidReview/blob/master/算法.md)
7 | * [设计模式与架构](https://github.com/huannan/AndroidReview/blob/master/设计模式与架构.md)
8 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 |
4 | android {
5 | compileSdkVersion 28
6 | defaultConfig {
7 | applicationId "com.nan.androidreview"
8 | minSdkVersion 15
9 | targetSdkVersion 28
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 |
14 | javaCompileOptions {
15 | annotationProcessorOptions {
16 | arguments = [moduleName: project.getName()]
17 | }
18 | }
19 | }
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 | }
27 |
28 | dependencies {
29 | implementation fileTree(include: ['*.jar'], dir: 'libs')
30 | implementation 'com.android.support:appcompat-v7:28.0.0'
31 | implementation 'com.android.support:support-v4:28.0.0'
32 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
33 | testImplementation 'junit:junit:4.12'
34 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
35 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
36 | implementation 'com.github.bumptech.glide:glide:4.7.1'
37 | annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
38 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
39 | implementation 'io.reactivex.rxjava2:rxjava:2.0.7'
40 | implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar'
41 | //路由
42 | implementation 'com.alibaba:arouter-api:1.2.1.1'
43 | annotationProcessor 'com.alibaba:arouter-compiler:1.1.2.1'
44 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
45 |
46 | implementation 'com.google.dagger:dagger:2.10'
47 | annotationProcessor 'com.google.dagger:dagger-compiler:2.10'
48 | }
49 | repositories {
50 | mavenCentral()
51 | }
52 |
53 | ////配置lint的jar包
54 | //configurations {
55 | // lintJarImport
56 | //}
57 | //
58 | //dependencies {
59 | // lintJarImport project(path: ":lint", configuration: "lintJarOutput")
60 | //}
61 | //
62 | ////将jar复制到lint目录下的lint.jar,因为在 lint 命令执行时会检查该文件,存在的话会添加到 lint 检查的队列中
63 | //task copyLintJar(type: Copy) {
64 | // from(configurations.lintJarImport) {
65 | // rename {
66 | // String fileName ->
67 | // 'lint.jar'
68 | // }
69 | // }
70 | // into 'build/intermediates/lint/'
71 | //}
72 | //
73 | ////当 Project 创建完所有任务的有向图后,通过 afterEvaluate 函数设置一个回调 Closure。将 copyLintJar 插入到 compileLint 之前执行
74 | ////Closure 里,我 disable 了所有 Debug 的 Task
75 | //project.afterEvaluate {
76 | // def compileLintTask = project.tasks.find { it.name == 'compileLint' }
77 | // compileLintTask.dependsOn(copyLintJar)
78 | //}
79 |
80 |
81 | apply plugin: 'kotlin-android-extensions'
82 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/nan/androidreview/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.nan.androidreview", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/assets/test.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huannan/AndroidReview/e15f26864f71f55a14148065300b2d73858135ce/app/src/main/assets/test.html
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/App.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import android.app.Application;
4 | import android.os.Build;
5 |
6 | import com.alibaba.android.arouter.launcher.ARouter;
7 |
8 | public class App extends Application {
9 |
10 | @Override
11 | public void onCreate() {
12 | super.onCreate();
13 |
14 | ARouter.openLog();
15 | if (BuildConfig.DEBUG) {
16 | // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
17 | ARouter.openDebug();
18 | }
19 | // 尽可能早,推荐在Application中初始化
20 | ARouter.init(this);
21 |
22 | Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
23 | @Override
24 | public void uncaughtException(Thread t, Throwable e) {
25 |
26 | }
27 | });
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/BitmapUtils.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import android.content.Context;
4 | import android.content.res.AssetManager;
5 | import android.content.res.Resources;
6 | import android.graphics.Bitmap;
7 | import android.graphics.BitmapFactory;
8 | import android.graphics.Canvas;
9 | import android.graphics.Matrix;
10 | import android.graphics.Paint;
11 | import android.graphics.PixelFormat;
12 | import android.graphics.PorterDuff;
13 | import android.graphics.PorterDuffXfermode;
14 | import android.graphics.Rect;
15 | import android.graphics.RectF;
16 | import android.graphics.drawable.BitmapDrawable;
17 | import android.graphics.drawable.Drawable;
18 | import android.media.ExifInterface;
19 | import android.text.TextUtils;
20 | import android.view.View;
21 |
22 | import java.io.BufferedOutputStream;
23 | import java.io.ByteArrayInputStream;
24 | import java.io.ByteArrayOutputStream;
25 | import java.io.File;
26 | import java.io.FileInputStream;
27 | import java.io.FileOutputStream;
28 | import java.io.IOException;
29 | import java.io.InputStream;
30 |
31 | public class BitmapUtils {
32 |
33 | /**
34 | * 从本地(SDcard)文件读取方式一
35 | *
36 | * @param filePath 文件路径
37 | * @param width 宽
38 | * @param height 高
39 | * @return
40 | */
41 | public static Bitmap readBitmapFromFile(String filePath, int width, int height) {
42 | BitmapFactory.Options options = new BitmapFactory.Options();
43 | options.inJustDecodeBounds = true;
44 | BitmapFactory.decodeFile(filePath, options);
45 | float srcWidth = options.outWidth;
46 | float srcHeight = options.outHeight;
47 | int inSampleSize = 1;
48 |
49 | if (srcHeight > height || srcWidth > width) {
50 | if (srcWidth > srcHeight) {
51 | inSampleSize = Math.round(srcHeight / height);
52 | } else {
53 | inSampleSize = Math.round(srcWidth / width);
54 | }
55 | }
56 |
57 | options.inJustDecodeBounds = false;
58 | options.inSampleSize = inSampleSize;
59 |
60 | return BitmapFactory.decodeFile(filePath, options);
61 | }
62 |
63 | /**
64 | * 从本地(SDcard)文件读取方式二
65 | *
66 | * @param filePath 文件路径
67 | * @param width 宽
68 | * @param height 高
69 | * @return
70 | */
71 | public static Bitmap readBitmapFromFileDescriptor(String filePath, int width, int height) {
72 | try {
73 | FileInputStream fis = new FileInputStream(filePath);
74 | BitmapFactory.Options options = new BitmapFactory.Options();
75 | options.inJustDecodeBounds = true;
76 | BitmapFactory.decodeFileDescriptor(fis.getFD(), null, options);
77 | float srcWidth = options.outWidth;
78 | float srcHeight = options.outHeight;
79 | int inSampleSize = 1;
80 |
81 | if (srcHeight > height || srcWidth > width) {
82 | if (srcWidth > srcHeight) {
83 | inSampleSize = Math.round(srcHeight / height);
84 | } else {
85 | inSampleSize = Math.round(srcWidth / width);
86 | }
87 | }
88 |
89 | options.inJustDecodeBounds = false;
90 | options.inSampleSize = inSampleSize;
91 |
92 | return BitmapFactory.decodeFileDescriptor(fis.getFD(), null, options);
93 | } catch (Exception ex) {
94 | }
95 | return null;
96 | }
97 |
98 | /**
99 | * 从输入流中读取文件(网络加载)
100 | *
101 | * @param ins 输入流
102 | * @param width 宽
103 | * @param height 高
104 | * @return
105 | */
106 | public static Bitmap readBitmapFromInputStream(InputStream ins, int width, int height) {
107 | BitmapFactory.Options options = new BitmapFactory.Options();
108 | options.inJustDecodeBounds = true;
109 | BitmapFactory.decodeStream(ins, null, options);
110 | float srcWidth = options.outWidth;
111 | float srcHeight = options.outHeight;
112 | int inSampleSize = 1;
113 |
114 | if (srcHeight > height || srcWidth > width) {
115 | if (srcWidth > srcHeight) {
116 | inSampleSize = Math.round(srcHeight / height);
117 | } else {
118 | inSampleSize = Math.round(srcWidth / width);
119 | }
120 | }
121 |
122 | options.inJustDecodeBounds = false;
123 | options.inSampleSize = inSampleSize;
124 |
125 | return BitmapFactory.decodeStream(ins, null, options);
126 | }
127 |
128 | /**
129 | * Res资源加载方式一。此种方式相当的耗费内存 建议采用decodeStream代替decodeResource
130 | *
131 | * @param resources
132 | * @param resourcesId
133 | * @param width
134 | * @param height
135 | * @return
136 | */
137 | public static Bitmap readBitmapFromResource(Resources resources, int resourcesId, int width, int height) {
138 | BitmapFactory.Options options = new BitmapFactory.Options();
139 | options.inJustDecodeBounds = true;
140 | BitmapFactory.decodeResource(resources, resourcesId, options);
141 | float srcWidth = options.outWidth;
142 | float srcHeight = options.outHeight;
143 | int inSampleSize = 1;
144 |
145 | if (srcHeight > height || srcWidth > width) {
146 | if (srcWidth > srcHeight) {
147 | inSampleSize = Math.round(srcHeight / height);
148 | } else {
149 | inSampleSize = Math.round(srcWidth / width);
150 | }
151 | }
152 |
153 | options.inJustDecodeBounds = false;
154 | options.inSampleSize = inSampleSize;
155 |
156 | return BitmapFactory.decodeResource(resources, resourcesId, options);
157 | }
158 |
159 | /**
160 | * Res资源加载方式二
161 | *
162 | * @param resources
163 | * @param resourcesId
164 | * @param width
165 | * @param height
166 | * @return
167 | */
168 | public static Bitmap readBitmapFromResourceStream(Resources resources, int resourcesId, int width, int height) {
169 | InputStream ins = resources.openRawResource(resourcesId);
170 | BitmapFactory.Options options = new BitmapFactory.Options();
171 | options.inJustDecodeBounds = true;
172 | BitmapFactory.decodeStream(ins, null, options);
173 | float srcWidth = options.outWidth;
174 | float srcHeight = options.outHeight;
175 | int inSampleSize = 1;
176 |
177 | if (srcHeight > height || srcWidth > width) {
178 | if (srcWidth > srcHeight) {
179 | inSampleSize = Math.round(srcHeight / height);
180 | } else {
181 | inSampleSize = Math.round(srcWidth / width);
182 | }
183 | }
184 |
185 | options.inJustDecodeBounds = false;
186 | options.inSampleSize = inSampleSize;
187 |
188 | return BitmapFactory.decodeStream(ins, null, options);
189 | }
190 |
191 | /**
192 | * Assets资源加载方式
193 | *
194 | * @param filePath 文件路径,即文件名称
195 | * @return
196 | */
197 | public static Bitmap readBitmapFromAssetsFile(Context context, String filePath) {
198 | Bitmap image = null;
199 | AssetManager am = context.getResources().getAssets();
200 | try {
201 | InputStream is = am.open(filePath);
202 | image = BitmapFactory.decodeStream(is);
203 | is.close();
204 | } catch (IOException e) {
205 | e.printStackTrace();
206 | }
207 | return image;
208 | }
209 |
210 | /**
211 | * 从二进制数据读取图片
212 | *
213 | * @param data
214 | * @param width
215 | * @param height
216 | * @return
217 | */
218 | public static Bitmap readBitmapFromByteArray(byte[] data, int width, int height) {
219 | BitmapFactory.Options options = new BitmapFactory.Options();
220 | options.inJustDecodeBounds = true;
221 | BitmapFactory.decodeByteArray(data, 0, data.length, options);
222 | float srcWidth = options.outWidth;
223 | float srcHeight = options.outHeight;
224 | int inSampleSize = 1;
225 |
226 | if (srcHeight > height || srcWidth > width) {
227 | if (srcWidth > srcHeight) {
228 | inSampleSize = Math.round(srcHeight / height);
229 | } else {
230 | inSampleSize = Math.round(srcWidth / width);
231 | }
232 | }
233 |
234 | options.inJustDecodeBounds = false;
235 | options.inSampleSize = inSampleSize;
236 |
237 | return BitmapFactory.decodeByteArray(data, 0, data.length, options);
238 | }
239 |
240 | /**
241 | * Drawable转化成Bitmap
242 | *
243 | * @param drawable
244 | * @return
245 | */
246 | public static Bitmap drawableToBitmap(Drawable drawable) {
247 | Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
248 | Canvas canvas = new Canvas(bitmap);
249 | drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
250 | drawable.draw(canvas);
251 | return bitmap;
252 | }
253 |
254 | /**
255 | * Bitmap转换成Drawable
256 | *
257 | * @param resources
258 | * @param bm
259 | * @return
260 | */
261 | public static Drawable bitmapToDrawable(Resources resources, Bitmap bm) {
262 | Drawable drawable = new BitmapDrawable(resources, bm);
263 | return drawable;
264 | }
265 |
266 | /**
267 | * Bitmap转换成byte[]
268 | *
269 | * @param bm
270 | * @return
271 | */
272 | public byte[] bitmap2Bytes(Bitmap bm) {
273 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
274 | bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
275 | return baos.toByteArray();
276 | }
277 |
278 | //byte[]转换成Bitmap
279 | //Bitmap bitmap = BitmapFactory.decodeByteArray(byte, 0, b.length);
280 |
281 | //InputStream转换成Bitmap
282 | //InputStream is = getResources().openRawResource(id);
283 | //Bitmap bitmap = BitmaoFactory.decodeStream(is);
284 |
285 | //InputStream转换成byte[]
286 | /*
287 | InputStream is = getResources().openRawResource(id);//也可以通过其他方式接收一个InputStream对象
288 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
289 | byte[] b = new byte[1024*2];
290 | int len = 0;
291 | while ((len = is.read(b, 0, b.length)) != -1){
292 | baos.write(b, 0, len);
293 | baos.flush();
294 | }
295 | byte[] bytes = baos.toByteArray();
296 | */
297 |
298 | public static void writeBitmapToFile(String filePath, Bitmap b, int quality) {
299 | try {
300 | File desFile = new File(filePath);
301 | FileOutputStream fos = new FileOutputStream(desFile);
302 | BufferedOutputStream bos = new BufferedOutputStream(fos);
303 | b.compress(Bitmap.CompressFormat.JPEG, quality, bos);
304 | bos.flush();
305 | bos.close();
306 | } catch (IOException e) {
307 | e.printStackTrace();
308 | }
309 | }
310 |
311 | private static Bitmap compressImage(Bitmap image) {
312 | if (image == null) {
313 | return null;
314 | }
315 | ByteArrayOutputStream baos = null;
316 | try {
317 | baos = new ByteArrayOutputStream();
318 | image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
319 | byte[] bytes = baos.toByteArray();
320 | ByteArrayInputStream isBm = new ByteArrayInputStream(bytes);
321 | Bitmap bitmap = BitmapFactory.decodeStream(isBm);
322 | return bitmap;
323 | } catch (OutOfMemoryError e) {
324 | } finally {
325 | try {
326 | if (baos != null) {
327 | baos.close();
328 | }
329 | } catch (IOException e) {
330 | }
331 | }
332 | return null;
333 | }
334 |
335 | /**
336 | * 根据scale生成一张图片
337 | *
338 | * @param bitmap
339 | * @param scale 等比缩放值
340 | * @return
341 | */
342 | public static Bitmap bitmapScale(Bitmap bitmap, float scale) {
343 | Matrix matrix = new Matrix();
344 | matrix.postScale(scale, scale); // 长和宽放大缩小的比例
345 | Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
346 | return resizeBmp;
347 | }
348 |
349 | /**
350 | * 读取照片exif信息中的旋转角度
351 | *
352 | * @param path 照片路径
353 | * @return角度
354 | */
355 | private static int readPictureDegree(String path) {
356 | if (TextUtils.isEmpty(path)) {
357 | return 0;
358 | }
359 | int degree = 0;
360 | try {
361 | ExifInterface exifInterface = new ExifInterface(path);
362 | int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
363 | switch (orientation) {
364 | case ExifInterface.ORIENTATION_ROTATE_90:
365 | degree = 90;
366 | break;
367 | case ExifInterface.ORIENTATION_ROTATE_180:
368 | degree = 180;
369 | break;
370 | case ExifInterface.ORIENTATION_ROTATE_270:
371 | degree = 270;
372 | break;
373 | }
374 | } catch (Exception e) {
375 | }
376 | return degree;
377 | }
378 |
379 | private static Bitmap rotateBitmap(Bitmap b, float rotateDegree) {
380 | if (b == null) {
381 | return null;
382 | }
383 | Matrix matrix = new Matrix();
384 | matrix.postRotate(rotateDegree);
385 | Bitmap rotaBitmap = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
386 | return rotaBitmap;
387 | }
388 |
389 | // 通过图片id获得Bitmap:
390 | // Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
391 |
392 | // 通过 assest 获取 获得Drawable bitmap:
393 | // InputStream in = this.getAssets().open("ic_launcher");
394 | // Drawable da = Drawable.createFromStream(in, null);
395 | // Bitmap mm = BitmapFactory.decodeStream(in);
396 | //
397 | // 通过 sdcard 获得 bitmap
398 | // Bitmap bit = BitmapFactory.decodeFile("/sdcard/android.jpg");
399 |
400 |
401 | public static Bitmap convertViewToBitmap(View view, int bitmapWidth, int bitmapHeight) {
402 | Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
403 | view.draw(new Canvas(bitmap));
404 | return bitmap;
405 | }
406 |
407 | public static Bitmap convertViewToBitMap(View view) {
408 | // 打开图像缓存
409 | view.setDrawingCacheEnabled(true);
410 | // 必须调用measure和layout方法才能成功保存可视组件的截图到png图像文件
411 | // 测量View大小
412 | view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
413 | // 发送位置和尺寸到View及其所有的子View
414 | view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
415 | // 获得可视组件的截图
416 | Bitmap bitmap = view.getDrawingCache();
417 | return bitmap;
418 | }
419 |
420 | public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) {
421 | int width = bitmap.getWidth();
422 | int height = bitmap.getHeight();
423 | Matrix matrix = new Matrix();
424 | float scaleWidht = ((float) w / width);
425 | float scaleHeight = ((float) h / height);
426 | matrix.postScale(scaleWidht, scaleHeight);
427 | Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
428 | return newbmp;
429 | }
430 |
431 | /**
432 | * 获得圆角图片的方法
433 | *
434 | * @param bitmap
435 | * @param roundPx
436 | * @return
437 | */
438 | public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
439 |
440 | Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
441 | .getHeight(), Bitmap.Config.ARGB_8888);
442 | Canvas canvas = new Canvas(output);
443 |
444 | final int color = 0xff424242;
445 | final Paint paint = new Paint();
446 | final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
447 | final RectF rectF = new RectF(rect);
448 |
449 | paint.setAntiAlias(true);
450 | canvas.drawARGB(0, 0, 0, 0);
451 | paint.setColor(color);
452 | canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
453 |
454 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
455 | canvas.drawBitmap(bitmap, rect, rect, paint);
456 |
457 | return output;
458 | }
459 |
460 | /**
461 | * 对bitmap进行裁剪
462 | *
463 | * @param context
464 | * @param id
465 | * @param x
466 | * @param y
467 | * @return
468 | */
469 | public Bitmap bitmapClip(Context context, int id, int x, int y) {
470 | Bitmap map = BitmapFactory.decodeResource(context.getResources(), id);
471 | map = Bitmap.createBitmap(map, x, y, 120, 120);
472 | return map;
473 | }
474 |
475 | public static Bitmap thumbnail(String path, int width, int height, boolean autoRotate) {
476 |
477 | //1. 获得Bitmap的宽高,但是不加载到内存
478 | BitmapFactory.Options options = new BitmapFactory.Options();
479 | options.inJustDecodeBounds = true;
480 | BitmapFactory.decodeFile(path, options);
481 | int srcWidth = options.outWidth;
482 | int srcHeight = options.outHeight;
483 |
484 | //2. 计算图片缩放倍数
485 | int inSampleSize = 1;
486 | if (srcHeight > height || srcWidth > width) {
487 | if (srcWidth > srcHeight) {
488 | inSampleSize = Math.round(srcHeight / height);
489 | } else {
490 | inSampleSize = Math.round(srcWidth / width);
491 | }
492 | }
493 |
494 | //3. 真正加载图片到内存当中
495 | options.inJustDecodeBounds = false;
496 | options.inSampleSize = inSampleSize;
497 | options.inPreferredConfig = Bitmap.Config.RGB_565;
498 | options.inPurgeable = true;
499 | options.inInputShareable = true;
500 | return BitmapFactory.decodeFile(path, options);
501 | }
502 |
503 | }
504 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/CacheManager.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import android.content.Context;
4 | import android.os.Environment;
5 |
6 | import java.io.File;
7 | import java.math.BigDecimal;
8 |
9 | public class CacheManager {
10 |
11 | public static String getTotalCacheSize(Context context) throws Exception {
12 | long cacheSize = getFolderSize(context.getCacheDir());
13 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
14 | cacheSize += getFolderSize(context.getExternalCacheDir());
15 | }
16 | return getFormatSize(cacheSize);
17 | }
18 |
19 |
20 | public static void clearAllCache(Context context) {
21 | deleteDir(context.getCacheDir());
22 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
23 | deleteDir(context.getExternalCacheDir());
24 | }
25 | }
26 |
27 | private static boolean deleteDir(File dir) {
28 | if (dir != null && dir.isDirectory()) {
29 | String[] children = dir.list();
30 | for (int i = 0; i < children.length; i++) {
31 | boolean success = deleteDir(new File(dir, children[i]));
32 | if (!success) {
33 | return false;
34 | }
35 | }
36 | }
37 | return dir.delete();
38 | }
39 |
40 | // 获取文件
41 | //Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据
42 | //Context.getExternalCacheDir() --> SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
43 | public static long getFolderSize(File file) throws Exception {
44 | long size = 0;
45 | try {
46 | File[] fileList = file.listFiles();
47 | for (int i = 0; i < fileList.length; i++) {
48 | // 如果下面还有文件
49 | if (fileList[i].isDirectory()) {
50 | size = size + getFolderSize(fileList[i]);
51 | } else {
52 | size = size + fileList[i].length();
53 | }
54 | }
55 | } catch (Exception e) {
56 | e.printStackTrace();
57 | }
58 | return size;
59 | }
60 |
61 | /**
62 | * 格式化单位
63 | *
64 | * @param size
65 | * @return
66 | */
67 | public static String getFormatSize(double size) {
68 | double kiloByte = size / 1024;
69 | if (kiloByte < 1) {
70 | // return size + "Byte";
71 | return "0K";
72 | }
73 |
74 | double megaByte = kiloByte / 1024;
75 | if (megaByte < 1) {
76 | BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
77 | return result1.setScale(2, BigDecimal.ROUND_HALF_UP)
78 | .toPlainString() + "KB";
79 | }
80 |
81 | double gigaByte = megaByte / 1024;
82 | if (gigaByte < 1) {
83 | BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
84 | return result2.setScale(2, BigDecimal.ROUND_HALF_UP)
85 | .toPlainString() + "MB";
86 | }
87 |
88 | double teraBytes = gigaByte / 1024;
89 | if (teraBytes < 1) {
90 | BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
91 | return result3.setScale(2, BigDecimal.ROUND_HALF_UP)
92 | .toPlainString() + "GB";
93 | }
94 | BigDecimal result4 = new BigDecimal(teraBytes);
95 | return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()
96 | + "TB";
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/ConstraintLayoutActivity.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 |
6 | public class ConstraintLayoutActivity extends AppCompatActivity {
7 |
8 | @Override
9 | protected void onCreate(Bundle savedInstanceState) {
10 | super.onCreate(savedInstanceState);
11 | setContentView(R.layout.activity_constraint_layout);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/ExceptionDemo.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import javax.xml.transform.Source;
4 |
5 | public class ExceptionDemo {
6 |
7 | public static void main(String[] args) {
8 | test4();
9 | }
10 |
11 | public static void test1() {
12 |
13 | try {
14 | //System.exit(0);
15 | int i = 1/0;
16 | } catch (Exception e) {
17 | System.exit(0);
18 | }finally {
19 | System.out.println("finally");
20 | }
21 |
22 | }
23 |
24 |
25 | public static int test2() {
26 | int a = 0;
27 | try {
28 | return a = 1;
29 | } catch (Exception e) {
30 | System.exit(0);
31 | }finally {
32 | a = 2;
33 | System.out.println("finally");
34 | }
35 | return 0;
36 | }
37 |
38 | public static int test3() {
39 | int a = 0;
40 | try {
41 | return a = 1;
42 | } catch (Exception e) {
43 |
44 | }finally {
45 | a = 2;
46 | System.out.println("finally");
47 | return a;
48 | }
49 | }
50 |
51 | public static void test4() {
52 | try {
53 | int a = 1/0;
54 | } catch (Exception e) {
55 | System.out.println("catch");
56 | int b = 1 / 0;
57 | }finally {
58 | System.out.println("finally");
59 | return;
60 | }
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/Fruit.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 | import java.lang.reflect.Field;
9 |
10 | public class Fruit {
11 |
12 | @Target(ElementType.FIELD)
13 | @Retention(RetentionPolicy.RUNTIME)
14 | @Documented
15 | public @interface FruitName {
16 |
17 | String value() default "";
18 |
19 | }
20 |
21 | @Target(ElementType.FIELD)
22 | @Retention(RetentionPolicy.RUNTIME)
23 | @Documented
24 | public @interface FruitColor {
25 |
26 | enum Color {BLUE, RED, GREEN}
27 |
28 | Color value() default Color.GREEN;
29 |
30 | }
31 |
32 | @Target(ElementType.FIELD)
33 | @Retention(RetentionPolicy.RUNTIME)
34 | @Documented
35 | public @interface FruitProvider {
36 |
37 | int id() default -1;
38 |
39 | String name() default "";
40 |
41 | String address() default "";
42 | }
43 |
44 | public class Apple {
45 |
46 | @FruitName("Apple")
47 | private String appleName;
48 |
49 | @FruitColor(FruitColor.Color.RED)
50 | private String appleColor;
51 |
52 | @FruitProvider(id = 1, name = "陕西红富士集团", address = "陕西省西安市延安路89号红富士大厦")
53 | private String appleProvider;
54 |
55 | public void setAppleColor(String appleColor) {
56 | this.appleColor = appleColor;
57 | }
58 |
59 | public String getAppleColor() {
60 | return appleColor;
61 | }
62 |
63 | public void setAppleName(String appleName) {
64 | this.appleName = appleName;
65 | }
66 |
67 | public String getAppleName() {
68 | return appleName;
69 | }
70 |
71 | public void setAppleProvider(String appleProvider) {
72 | this.appleProvider = appleProvider;
73 | }
74 |
75 | public String getAppleProvider() {
76 | return appleProvider;
77 | }
78 |
79 | public void displayName() {
80 | System.out.println("水果的名字是:苹果");
81 | }
82 | }
83 |
84 | public static class FruitInfoUtil {
85 | public void getFruitInfo(Class> clazz) {
86 |
87 | String strFruitName = " 水果名称:";
88 | String strFruitColor = " 水果颜色:";
89 | String strFruitProvicer = "供应商信息:";
90 |
91 | Field[] fields = clazz.getDeclaredFields();
92 |
93 | for (Field field : fields) {
94 | if (field.isAnnotationPresent(FruitName.class)) {
95 | FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);
96 | strFruitName = strFruitName + fruitName.value();
97 | System.out.println(strFruitName);
98 | } else if (field.isAnnotationPresent(FruitColor.class)) {
99 | FruitColor fruitColor = (FruitColor) field.getAnnotation(FruitColor.class);
100 | strFruitColor = strFruitColor + fruitColor.value().toString();
101 | System.out.println(strFruitColor);
102 | } else if (field.isAnnotationPresent(FruitProvider.class)) {
103 | FruitProvider fruitProvider = (FruitProvider) field.getAnnotation(FruitProvider.class);
104 | strFruitProvicer = " 供应商编号:" + fruitProvider.id() + " 供应商名称:" + fruitProvider.name() + " 供应商地址:" + fruitProvider.address();
105 | System.out.println(strFruitProvicer);
106 | }
107 | }
108 | }
109 | }
110 |
111 | public static void main(String[] args) {
112 | FruitInfoUtil util = new FruitInfoUtil();
113 | util.getFruitInfo(Apple.class);
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/HandlerThreadActivity.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import android.os.Bundle;
4 | import android.os.Handler;
5 | import android.os.HandlerThread;
6 | import android.os.Message;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.widget.TextView;
9 |
10 | import com.alibaba.android.arouter.facade.annotation.Route;
11 |
12 | @Route(path = "/com/a1")
13 | public class HandlerThreadActivity extends AppCompatActivity {
14 |
15 | private TextView tvMain;
16 |
17 | private HandlerThread mHandlerThread;
18 | //子线程中的handler
19 | private Handler mThreadHandler;
20 | //UI线程中的handler
21 | private Handler mMainHandler = new Handler();
22 |
23 | //以防退出界面后Handler还在执行
24 | private boolean isUpdateInfo;
25 | //用以表示该handler的常量
26 | private static final int MSG_UPDATE_INFO = 0x110;
27 |
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_test1);
32 |
33 | tvMain = (TextView) findViewById(R.id.tv_main);
34 |
35 | initThread();
36 | }
37 |
38 |
39 | private void initThread() {
40 | mHandlerThread = new HandlerThread("check-message-coming");
41 | mHandlerThread.start();
42 |
43 | mThreadHandler = new Handler(mHandlerThread.getLooper()) {
44 | @Override
45 | public void handleMessage(Message msg) {
46 | update();//模拟数据更新
47 |
48 | if (isUpdateInfo) {
49 | //通过持有 HandlerThread的Looper 的 mThreadHandler去发送消息,触发HandlerThread工作
50 | mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
51 | }
52 | }
53 | };
54 |
55 | }
56 |
57 | private void update() {
58 | try {
59 | //模拟耗时
60 | Thread.sleep(2000);
61 | mMainHandler.post(new Runnable() {
62 | @Override
63 | public void run() {
64 | String result = "每隔2秒更新一下数据:";
65 | result += Math.random();
66 | tvMain.setText(result);
67 | }
68 | });
69 |
70 | } catch (InterruptedException e) {
71 | e.printStackTrace();
72 | }
73 |
74 | }
75 |
76 | @Override
77 | protected void onResume() {
78 | super.onResume();
79 | //开始查询
80 | isUpdateInfo = true;
81 | mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
82 | }
83 |
84 | @Override
85 | protected void onPause() {
86 | super.onPause();
87 | //停止查询
88 | //以防退出界面后Handler还在执行
89 | isUpdateInfo = false;
90 | mThreadHandler.removeMessages(MSG_UPDATE_INFO);
91 | }
92 |
93 | @Override
94 | protected void onDestroy() {
95 | super.onDestroy();
96 | //释放资源
97 | mHandlerThread.quit();
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import android.Manifest;
4 | import android.app.ActivityManager;
5 | import android.content.Context;
6 | import android.content.pm.PackageManager;
7 | import android.os.AsyncTask;
8 | import android.support.annotation.NonNull;
9 | import android.support.v4.app.ActivityCompat;
10 | import android.support.v4.app.Fragment;
11 | import android.support.v4.content.ContextCompat;
12 | import android.support.v7.app.AppCompatActivity;
13 | import android.os.Bundle;
14 | import android.util.Log;
15 | import android.view.View;
16 | import android.widget.TextView;
17 | import android.widget.Toast;
18 |
19 | import com.alibaba.android.arouter.launcher.ARouter;
20 | import com.bumptech.glide.Glide;
21 | import com.tbruyelle.rxpermissions2.Permission;
22 | import com.tbruyelle.rxpermissions2.RxPermissions;
23 |
24 | import io.reactivex.functions.Consumer;
25 |
26 | public class MainActivity extends AppCompatActivity {
27 |
28 | public static final String TAG = MainActivity.class.getSimpleName();
29 | private TextView tv_test;
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | setContentView(R.layout.activity_main);
35 |
36 | tv_test = findViewById(R.id.tv_test);
37 |
38 | //requestPermissions();
39 | //testFragment();
40 | //testAsyncTask();
41 | //testIntentService();
42 | //testMemory();
43 | //testBitmap();
44 | //testCache();
45 | //testRouter();
46 | testPermissions();
47 | }
48 |
49 | public static final int CODE_READ_CONTACTS = 0x01;
50 |
51 | private void testPermissions() {
52 |
53 | if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
54 | != PackageManager.PERMISSION_GRANTED) {
55 |
56 | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, CODE_READ_CONTACTS);
57 |
58 | } else {
59 |
60 | Toast.makeText(this, "权限已经正确授予", Toast.LENGTH_SHORT).show();
61 |
62 | }
63 |
64 | }
65 |
66 | @Override
67 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
68 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
69 | switch (requestCode) {
70 | case CODE_READ_CONTACTS: {
71 | if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
72 |
73 | // permission was granted, yay! Do the
74 | // contacts-related task you need to do.
75 |
76 | Toast.makeText(this, "权限已经正确授予", Toast.LENGTH_SHORT).show();
77 |
78 | } else {
79 |
80 | // permission denied, boo! Disable the
81 | // functionality that depends on this permission.
82 |
83 | Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
84 | }
85 | }
86 | }
87 | }
88 |
89 | private void testRouter() {
90 | tv_test.setOnClickListener(new View.OnClickListener() {
91 | @Override
92 | public void onClick(View v) {
93 | ARouter.getInstance()
94 | .build("/com/a1")
95 | .withInt("i", 1)
96 | .navigation(MainActivity.this, 100);
97 | }
98 | });
99 | }
100 |
101 | private void testCache() {
102 |
103 | String cache = "0kb";
104 | try {
105 | cache = CacheManager.getTotalCacheSize(this);
106 | } catch (Exception e) {
107 | e.printStackTrace();
108 | }
109 | tv_test.setText(cache);
110 |
111 | }
112 |
113 | private void testBitmap() {
114 |
115 | //Glide.with(this).load()
116 |
117 | }
118 |
119 | private void requestPermissions() {
120 | RxPermissions rxPermission = new RxPermissions(this);
121 | rxPermission
122 | .requestEach(Manifest.permission.ACCESS_FINE_LOCATION,
123 | Manifest.permission.WRITE_EXTERNAL_STORAGE,
124 | Manifest.permission.READ_CALENDAR,
125 | Manifest.permission.READ_CALL_LOG,
126 | Manifest.permission.READ_CONTACTS,
127 | Manifest.permission.READ_PHONE_STATE,
128 | Manifest.permission.READ_SMS,
129 | Manifest.permission.RECORD_AUDIO,
130 | Manifest.permission.CAMERA,
131 | Manifest.permission.CALL_PHONE,
132 | Manifest.permission.SEND_SMS)
133 | .subscribe(new Consumer() {
134 | @Override
135 | public void accept(Permission permission) throws Exception {
136 | if (permission.granted) {
137 | // 用户已经同意该权限
138 | Log.d(TAG, permission.name + " is granted.");
139 | } else if (permission.shouldShowRequestPermissionRationale) {
140 | // 用户拒绝了该权限,没有选中『不再询问』(Never ask again),那么下次再次启动时,还会提示请求权限的对话框
141 | Log.d(TAG, permission.name + " is denied. More info should be provided.");
142 | } else {
143 | // 用户拒绝了该权限,并且选中『不再询问』
144 | Log.d(TAG, permission.name + " is denied.");
145 | }
146 | }
147 | });
148 | }
149 |
150 |
151 | private void testMemory() {
152 | ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
153 | int memoryClass = am.getMemoryClass();
154 | tv_test.setText(memoryClass + "");
155 | }
156 |
157 | private void testIntentService() {
158 |
159 | }
160 |
161 |
162 | public void testFragment() {
163 | Fragment fragment = new TestFragment();
164 | Bundle bundle = new Bundle();
165 | bundle.putString("key", "value");
166 | fragment.setArguments(bundle);
167 | getSupportFragmentManager().beginTransaction()
168 | .add(R.id.fragment_container, fragment, "test")
169 | .commit();
170 | }
171 |
172 | public void tesetAsyncTask() {
173 | TestAsyncTask testAsyncTask = new TestAsyncTask();
174 | testAsyncTask.execute("1", "2", "3");
175 | }
176 |
177 | class TestAsyncTask extends AsyncTask {
178 |
179 | @Override
180 | protected void onPreExecute() {
181 | super.onPreExecute();
182 | Log.i(TAG, "onPreExecute");
183 | }
184 |
185 | @Override
186 | protected String doInBackground(String... strings) {
187 |
188 | StringBuilder sb = new StringBuilder();
189 |
190 | for (int i = 0; i < strings.length; i++) {
191 |
192 | try {
193 | Thread.sleep(1000);
194 | } catch (InterruptedException e) {
195 | e.printStackTrace();
196 | }
197 |
198 | sb.append(strings[i]);
199 | onProgressUpdate((i + 1) * 100 / strings.length);
200 | }
201 |
202 | return sb.toString();
203 | }
204 |
205 | @Override
206 | protected void onProgressUpdate(Integer... values) {
207 | super.onProgressUpdate(values);
208 | Log.i(TAG, "onProgressUpdate: " + values[0]);
209 | }
210 |
211 | @Override
212 | protected void onPostExecute(String s) {
213 | super.onPostExecute(s);
214 | Log.i(TAG, "onPostExecute: " + s);
215 | }
216 |
217 | @Override
218 | protected void onCancelled(String s) {
219 | super.onCancelled(s);
220 | Log.i(TAG, "onCancelled: " + s);
221 | }
222 | }
223 |
224 |
225 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/Sample.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Target;
6 | import java.util.ArrayList;
7 | import java.util.Arrays;
8 | import java.util.List;
9 |
10 | public class Sample {
11 |
12 | @Target(ElementType.TYPE)
13 | public @interface Table {
14 | String tableName() default "name";
15 | }
16 |
17 | @Documented
18 | @Table(tableName = "c1")
19 | public @interface NoDBColumn {
20 |
21 | }
22 |
23 | //因为类被new出来之后是存放在堆中的,所有成员变量全部存储于堆中(包括基本数据类型,引用和引用的对象实体)
24 | @NoDBColumn
25 | int i1 = 0;
26 | Sample s1 = new Sample();
27 |
28 | public void method() {
29 | //局部变量和引用变量都是存在于栈中,但引用变量指向的对象是存在于堆中
30 | int i2 = 1;
31 | Sample s2 = new Sample();
32 | }
33 |
34 | public static void main(String[] args) {
35 | //局部变量和引用变量都是存在于栈中,但引用变量指向的对象是存在于堆中
36 | Sample s3 = new Sample();
37 | }
38 |
39 |
40 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/TestFragment.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.NonNull;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | public class TestFragment extends Fragment {
12 |
13 | @Nullable
14 | @Override
15 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
16 | return inflater.inflate(R.layout.activity_main, container, false);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/TestIntentService.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import android.app.IntentService;
4 | import android.content.Intent;
5 | import android.support.annotation.Nullable;
6 |
7 | public class TestIntentService extends IntentService {
8 |
9 | public TestIntentService() {
10 | super("TestIntentService");
11 | }
12 |
13 |
14 | @Override
15 | protected void onHandleIntent(@Nullable Intent intent) {
16 |
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/TestThread.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import java.util.concurrent.ThreadPoolExecutor;
4 |
5 | public class TestThread {
6 |
7 | static int i1; int geti1() { return i1; }
8 |
9 | volatile int i2; int geti2() { return i2; }
10 |
11 | int i3; synchronized int geti3() { return i3; }
12 |
13 | public static void main(String[] args) {
14 |
15 |
16 | MyRunnable myRunnable = new MyRunnable("run 1");
17 |
18 | Thread thread = new Thread(myRunnable);
19 | thread.start();
20 |
21 | Error e;
22 | OutOfMemoryError error;
23 | }
24 |
25 | public synchronized void test1() {
26 |
27 | }
28 |
29 | public final void test2() {
30 | synchronized (this) {
31 |
32 | }
33 | }
34 |
35 | public final void test2(int i) {
36 | synchronized (this) {
37 |
38 | }
39 | }
40 |
41 | class MyThread extends Thread {
42 |
43 | @Override
44 | public void run() {
45 | super.run();
46 |
47 | }
48 | }
49 |
50 | static class MyRunnable implements Runnable {
51 |
52 | volatile private String mName;
53 |
54 | public MyRunnable(String name) {
55 | mName = name;
56 | }
57 |
58 | @Override
59 | public void run() {
60 | try {
61 | Thread.sleep(1000);
62 | System.out.println(mName);
63 | } catch (Exception e) {
64 | e.printStackTrace();
65 | }
66 | }
67 | }
68 |
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/nan/androidreview/TestType.java:
--------------------------------------------------------------------------------
1 | package com.nan.androidreview;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class TestType {
7 |
8 | T a[];
9 |
10 | public static void main(String[] args) throws Exception {
11 |
12 | List list = new ArrayList<>();
13 | list.getClass().getMethod("add", Object.class).invoke(list, "abc");
14 |
15 | // List