@ -1,38 +0,0 @@ |
|||||||
--- |
|
||||||
Activity |
|
||||||
--- |
|
||||||
|
|
||||||
#### 目录 |
|
||||||
|
|
||||||
1. 思维导图 |
|
||||||
2. 基本使用 |
|
||||||
|
|
||||||
- Activity 启动以及生命周期 |
|
||||||
- Activity 启动 |
|
||||||
- 显式启动 |
|
||||||
- 隐式启动 |
|
||||||
- 生命周期 |
|
||||||
- 正常生命周期 |
|
||||||
- 异常生命周期 |
|
||||||
- 横竖屏切换 |
|
||||||
- 异常退出 |
|
||||||
- 启动模式 |
|
||||||
- standard |
|
||||||
- singleTop |
|
||||||
- singleTask |
|
||||||
- singleInstance |
|
||||||
- 常用回调函数 |
|
||||||
|
|
||||||
- setResult / onActivityResult |
|
||||||
|
|
||||||
- onNewIntent |
|
||||||
- onConfigurationChanged |
|
||||||
- onSaveInstanceState / onRestoreInstanceState |
|
||||||
- onTrimMemory |
|
||||||
- 通信交互 |
|
||||||
|
|
||||||
- 与 Activity 通信 |
|
||||||
- 与 Fragment 通信 |
|
||||||
- 与 Service 通信 |
|
||||||
3. 高级玩法 |
|
||||||
- 根 Activity 启动流程 |
|
@ -0,0 +1,25 @@ |
|||||||
|
--- |
||||||
|
AsyncTask |
||||||
|
--- |
||||||
|
|
||||||
|
#### 目录 |
||||||
|
|
||||||
|
1. 思维导图 |
||||||
|
2. 概述 |
||||||
|
3. 具体使用 |
||||||
|
4. 源码分析 |
||||||
|
5. 参考 |
||||||
|
|
||||||
|
#### 思维导图 |
||||||
|
|
||||||
|
#### 概述 |
||||||
|
|
||||||
|
AsyncTask 是一个轻量级的异步任务类、抽象泛型类。 |
||||||
|
|
||||||
|
#### 具体使用 |
||||||
|
|
||||||
|
#### 源码分析 |
||||||
|
|
||||||
|
#### 参考 |
||||||
|
|
||||||
|
[译文:Android中糟糕的AsyncTask](https://droidyue.com/blog/2014/11/08/bad-smell-of-asynctask-in-android/) |
@ -0,0 +1,172 @@ |
|||||||
|
--- |
||||||
|
HandlerThread |
||||||
|
--- |
||||||
|
|
||||||
|
#### 目录 |
||||||
|
|
||||||
|
1. 思维导图 |
||||||
|
2. 概述 |
||||||
|
3. 具体使用 |
||||||
|
4. 源码分析 |
||||||
|
5. 参考 |
||||||
|
|
||||||
|
#### 思维导图 |
||||||
|
|
||||||
|
#### 概述 |
||||||
|
|
||||||
|
HandlerThread 继承于 Thread,所以它本质就是个 Thread。与普通 Thread 的区别在于,它不仅建立了一个线程,并且创建了消息队列,有自己的 Looper,可以让我们在自己的线程中分发和处理消息,并对外提供自己的 Looper 的 get 方法。 |
||||||
|
|
||||||
|
HandlerThread 自带 Looper 使它可以通过消息队列来重复使用当前线程,节省系统资源开销。这是它的优点也是缺点,每个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。 |
||||||
|
|
||||||
|
#### 具体使用 |
||||||
|
|
||||||
|
```java |
||||||
|
public class HandlerThreadActivity extends AppCompatActivity { |
||||||
|
|
||||||
|
private Button mButton; |
||||||
|
private HandlerThread mHandlerThread; |
||||||
|
private Handler mUiHandler; |
||||||
|
private Handler mChildHandler; |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) { |
||||||
|
super.onCreate(savedInstanceState); |
||||||
|
setContentView(R.layout.activity_handler); |
||||||
|
initView(); |
||||||
|
|
||||||
|
mHandlerThread = new HandlerThread("HandlerThread"); |
||||||
|
mHandlerThread.start(); |
||||||
|
mUiHandler = new Handler(new Handler.Callback() { |
||||||
|
@Override |
||||||
|
public boolean handleMessage(Message msg) { |
||||||
|
if (msg.what == 2) { |
||||||
|
mButton.setText("子线程更新"); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
}); |
||||||
|
mChildHandler = new Handler(mHandlerThread.getLooper(), new Handler.Callback() { |
||||||
|
@Override |
||||||
|
public boolean handleMessage(Message msg) { |
||||||
|
if (msg.what == 1) { |
||||||
|
try { |
||||||
|
//子线程模拟延迟处理 |
||||||
|
Thread.sleep(2000); |
||||||
|
mUiHandler.sendEmptyMessage(2); |
||||||
|
} catch (InterruptedException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void initView() { |
||||||
|
mButton = findViewById(R.id.btn_show); |
||||||
|
mButton.setOnClickListener(new View.OnClickListener() { |
||||||
|
@Override |
||||||
|
public void onClick(View v) { |
||||||
|
mChildHandler.sendEmptyMessage(1); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
#### 源码分析 |
||||||
|
|
||||||
|
```java |
||||||
|
public class HandlerThread extends Thread { |
||||||
|
int mPriority; |
||||||
|
int mTid = -1; |
||||||
|
Looper mLooper; |
||||||
|
private @Nullable Handler mHandler; |
||||||
|
|
||||||
|
public HandlerThread(String name) { |
||||||
|
super(name); |
||||||
|
mPriority = Process.THREAD_PRIORITY_DEFAULT; |
||||||
|
} |
||||||
|
|
||||||
|
public HandlerThread(String name, int priority) { |
||||||
|
super(name); |
||||||
|
mPriority = priority; |
||||||
|
} |
||||||
|
|
||||||
|
protected void onLooperPrepared() { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
mTid = Process.myTid(); |
||||||
|
Looper.prepare(); |
||||||
|
synchronized (this) { |
||||||
|
mLooper = Looper.myLooper(); |
||||||
|
notifyAll(); |
||||||
|
} |
||||||
|
Process.setThreadPriority(mPriority); |
||||||
|
onLooperPrepared(); |
||||||
|
Looper.loop(); |
||||||
|
mTid = -1; |
||||||
|
} |
||||||
|
|
||||||
|
public Looper getLooper() { |
||||||
|
if (!isAlive()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
synchronized (this) { |
||||||
|
while (isAlive() && mLooper == null) { |
||||||
|
try { |
||||||
|
wait(); |
||||||
|
} catch (InterruptedException e) { |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return mLooper; |
||||||
|
} |
||||||
|
|
||||||
|
@NonNull |
||||||
|
public Handler getThreadHandler() { |
||||||
|
if (mHandler == null) { |
||||||
|
mHandler = new Handler(getLooper()); |
||||||
|
} |
||||||
|
return mHandler; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean quit() { |
||||||
|
Looper looper = getLooper(); |
||||||
|
if (looper != null) { |
||||||
|
looper.quit(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean quitSafely() { |
||||||
|
Looper looper = getLooper(); |
||||||
|
if (looper != null) { |
||||||
|
looper.quitSafely(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public int getThreadId() { |
||||||
|
return mTid; |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
源码很简单,就是在 run 方法中执行 Looper.prepare()、Looper.loop() 构造消息循环系统。外界可以通过 getLooper() 这个方法拿到这个 Looper。 |
||||||
|
|
||||||
|
总结为下: |
||||||
|
|
||||||
|
1. HandlerThread 是一个自带 Looper 的线程,因此只能作为子线程使用 |
||||||
|
2. HandlerThread 必须配合 Handler 使用,HandlerThread 线程中具体做什么事,需要在 Handler 的 callback 中进行,因为它自己的 run 方法被写死了 |
||||||
|
3. 子线程的 Handler 与 HandlerThread 关系建立是通过构造子线程的Handler 传入 HandlerThread 的 Looper 。所以在此之前,必须先调用 mHandlerThread.start 让 run 方法跑起来 Looper 才能创建。 |
||||||
|
|
||||||
|
#### 参考 |
||||||
|
|
||||||
|
[Android中的线程形态(二)(HandlerThread/IntentService)](https://www.jianshu.com/p/4ca760e5040b) |
@ -0,0 +1,194 @@ |
|||||||
|
--- |
||||||
|
IntentService |
||||||
|
--- |
||||||
|
|
||||||
|
#### 目录 |
||||||
|
|
||||||
|
1. 思维导图 |
||||||
|
2. 概述 |
||||||
|
3. 具体使用 |
||||||
|
4. 源码分析 |
||||||
|
5. 参考 |
||||||
|
|
||||||
|
#### 思维导图 |
||||||
|
|
||||||
|
#### 概述 |
||||||
|
|
||||||
|
IntentService 是继承于 Service 并处理异步请求的一个类,内部实现是 HandlerThread,处理完子线程的事后自动 stopService。 |
||||||
|
|
||||||
|
#### 具体使用 |
||||||
|
|
||||||
|
首先创建: |
||||||
|
|
||||||
|
```java |
||||||
|
public class MyIntentService extends IntentService { |
||||||
|
|
||||||
|
private static final String TAG = "MyIntentService"; |
||||||
|
|
||||||
|
public MyIntentService() { |
||||||
|
//IntentService 工作线程的名字 |
||||||
|
super("MyIntentService"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCreate() { |
||||||
|
super.onCreate(); |
||||||
|
Log.i(TAG, "onCreate: "); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int onStartCommand(@Nullable Intent intent, int flags, int startId) { |
||||||
|
Log.i(TAG, "onStartCommand: "); |
||||||
|
return super.onStartCommand(intent, flags, startId); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onDestroy() { |
||||||
|
super.onDestroy(); |
||||||
|
Log.i(TAG, "onDestroy: "); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onHandleIntent(@Nullable Intent intent) { |
||||||
|
if (intent != null) { |
||||||
|
String taskName = intent.getStringExtra("taskName"); |
||||||
|
Log.i(TAG, "onHandleIntent: " + taskName); |
||||||
|
switch (taskName) { |
||||||
|
case "task1": |
||||||
|
//任务一 |
||||||
|
try { |
||||||
|
Thread.sleep(3000); |
||||||
|
} catch (InterruptedException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
break; |
||||||
|
case "task2": |
||||||
|
//任务二 |
||||||
|
break; |
||||||
|
default: |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
Activity 中: |
||||||
|
|
||||||
|
```java |
||||||
|
public void onClick(View v) { |
||||||
|
Intent intent = new Intent(this, MyIntentService.class); |
||||||
|
switch (v.getId()) { |
||||||
|
case R.id.btn1: |
||||||
|
intent.putExtra("taskName", "task1"); |
||||||
|
startService(intent); |
||||||
|
break; |
||||||
|
case R.id.btn2: |
||||||
|
intent.putExtra("taskName", "task2"); |
||||||
|
startService(intent); |
||||||
|
break; |
||||||
|
default: |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
这里如果点击按钮一后立马点击按钮二,日志打印如下: |
||||||
|
|
||||||
|
``` |
||||||
|
onCreate、onStartCommand、onHandleIntent: task1、 |
||||||
|
onStartCommand、onHandleIntent: task2、onDestroy |
||||||
|
``` |
||||||
|
|
||||||
|
如果是等三秒后再点击按钮二,就是: |
||||||
|
|
||||||
|
``` |
||||||
|
onCreate、onStartCommand、onHandleIntent: task1、onDestroy、 |
||||||
|
onCreate、onStartCommand、onHandleIntent: task2、onDestroy |
||||||
|
``` |
||||||
|
|
||||||
|
这下就清楚了吧。 |
||||||
|
|
||||||
|
#### 源码分析 |
||||||
|
|
||||||
|
```java |
||||||
|
public abstract class IntentService extends Service { |
||||||
|
private volatile Looper mServiceLooper; |
||||||
|
private volatile ServiceHandler mServiceHandler; |
||||||
|
private String mName; |
||||||
|
private boolean mRedelivery; |
||||||
|
|
||||||
|
private final class ServiceHandler extends Handler { |
||||||
|
public ServiceHandler(Looper looper) { |
||||||
|
super(looper); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void handleMessage(Message msg) { |
||||||
|
//重写的方法,子线程需要做的事情 |
||||||
|
onHandleIntent((Intent)msg.obj); |
||||||
|
//做完事,自动停止 |
||||||
|
stopSelf(msg.arg1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public IntentService(String name) { |
||||||
|
super(); |
||||||
|
//IntentService 的线程名 |
||||||
|
mName = name; |
||||||
|
} |
||||||
|
|
||||||
|
public void setIntentRedelivery(boolean enabled) { |
||||||
|
mRedelivery = enabled; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCreate() { |
||||||
|
super.onCreate(); |
||||||
|
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); |
||||||
|
thread.start(); |
||||||
|
|
||||||
|
//构造子线程 Handler |
||||||
|
mServiceLooper = thread.getLooper(); |
||||||
|
mServiceHandler = new ServiceHandler(mServiceLooper); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onStart(@Nullable Intent intent, int startId) { |
||||||
|
Message msg = mServiceHandler.obtainMessage(); |
||||||
|
msg.arg1 = startId; |
||||||
|
msg.obj = intent; |
||||||
|
//在 Service 启动的时候发送消息,子线程开始工作 |
||||||
|
mServiceHandler.sendMessage(msg); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int onStartCommand(@Nullable Intent intent, int flags, int startId) { |
||||||
|
//调用上面的那个方法,促使子线程开始工作 |
||||||
|
onStart(intent, startId); |
||||||
|
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onDestroy() { |
||||||
|
mServiceLooper.quit(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
@Nullable |
||||||
|
public IBinder onBind(Intent intent) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@WorkerThread |
||||||
|
protected abstract void onHandleIntent(@Nullable Intent intent); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
总结如下: |
||||||
|
|
||||||
|
1. Service onCreate 的时候通过 HandlerThread 构建子线程的 Handler |
||||||
|
2. Service onStartCommand 中通过子线程 Handler 发送消息 |
||||||
|
3. 子线程 handlerMessage 中调用我们重写的 onHandlerIntent 执行异步任务,执行完之后 Service 销毁 |
||||||
|
|
||||||
|
#### 参考 |
@ -0,0 +1,18 @@ |
|||||||
|
--- |
||||||
|
屏幕适配 |
||||||
|
--- |
||||||
|
|
||||||
|
#### 目录 |
||||||
|
|
||||||
|
1. 思维导图 |
||||||
|
2. 适配方案 |
||||||
|
3. 参考 |
||||||
|
|
||||||
|
#### 思维导图 |
||||||
|
|
||||||
|
#### 适配方案 |
||||||
|
|
||||||
|
#### 参考 |
||||||
|
|
||||||
|
[一种极低成本的Android屏幕适配方式](https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA) |
||||||
|
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 153 KiB |
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 285 KiB After Width: | Height: | Size: 285 KiB |
Before Width: | Height: | Size: 191 KiB After Width: | Height: | Size: 191 KiB |
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 155 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |