@ -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 |