Android知识总结
一、HandlerThread
HandlerThread是Thread的子类,严格意义上来说就是一个线程,只是它在自己的线程里面帮我们创建了Looper,使Handler的Message消息在子线程处理。
- 1) 方便使用:a. 方便初始化,b,方便获取线程looper
- 2)保证了线程安全
而我们要使用子线程中的Looper的方式是怎样的呢?看下面的代码
Thread thread = new Thread(new Runnable() {
Looper looper;
@Override
public void run() {
Log.d(TAG, "click2: " + Thread.currentThread().getName());
Looper.prepare();
looper =Looper.myLooper();
Looper.loop();
}
public Looper getLooper() {
return looper;
}
});
thread.start();
Handler handler = new Handler(thread.getLooper());
上面这段代码有没有问题呢?
- 1)在初始化子线程的handler的时候,我们无法将子线程的looper传值给Handler,解决办法有如下办法:
a. 可以将Handler的初始化放到 Thread里面进行
b. 可以创建一个独立的类继承Thread,然后,通过类的对象获取。- 2)依据多线程的工作原理,我们在上面的代码中,调用 thread.getLooper() 的时候,此时的looper可能还没有初始化,此时是不是可能会挂掉呢?
这两种办法都可以,但是,这个工作 HandlerThread帮我们完成了。
//创建Looper
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
//notifyAll(); 放到这里也是可以的,都是唤醒 wait() 是其拿到锁后在执行
mLooper = Looper.myLooper();
notifyAll(); //此时唤醒其他等待的锁,使其处于就绪态
//在这里会使 其他引用 wait() 的线程处于就绪状态,
//等 notifyAll() 这边释放锁后,wait() 获取锁在执行
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
//获取Looper
public Looper getLooper() {
if (!isAlive()) {
return null;
}
synchronized (this) {
//这边用 while 循环,主要是因为此处的 wait() 可能被其他地方的 notifyAll() 唤醒,
//此时这个线程的 mLooper == null,再次进行等待被唤醒。
while (isAlive() && mLooper == null) { //主要解决线程并发时 wait() 被唤醒和 wait() 异常唤醒的问题。
try {
wait();//当mLooper==null时,进入阻塞状态,并释放线程锁
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit(); //退出hander发送消息
return true;
}
return false;
}
wait()/ notifyAll()
的原理见Java基础-线程和进程(二)
二、IntentService
在Android开发中,我们或许会碰到这么一种业务需求,一项任务分成几个子任务,子任务按顺序先后执行,子任务全部执行完后,这项任务才算成功。那么,利用几个子线程顺序执行是可以达到这个目的的,但是每个线程必须去手动控制,而且得在一个子线程执行完后,再开启另一个子线程。或者,全部放到一个线程中让其顺序执行。这样都可以做到,但是,如果这是一个后台任务,就得放到Service里面,由于Service和Activity是同级的,所以,要执行耗时任务,就得在Service里面开子线程来执行。那么,有没有一种简单的方法来处理这个过程呢,答案就是IntentService。
IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们去手动控制。另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。
- 1)、原理
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);
}
}
@Override
public void onCreate() {
super.onCreate();
//创建HandlerThread
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
//创建Handler
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
//发送消息
mServiceHandler.sendMessage(msg);
}
//处理消息
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
//停止服务
public final void stopSelf(int startId) {
if (mActivityManager == null) {
return;
}
try {
mActivityManager.stopServiceToken(
new ComponentName(this, mClassName), mToken, startId);
} catch (RemoteException ex) {
}
}
IntentService
运用了HandlerThread
来获取Looper,然后通过Handler
来发送消息。
- 2)、实现
实现IntentService
public class IntentServiceDemo extends IntentService {
public IntentServiceDemo() {
//必须实现父类的构造方法
super("IntentServiceDemo");
}
@Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
return super.onBind(intent);
}
@Override
public void onCreate() {
System.out.println("onCreate");
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
System.out.println("onStart");
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void setIntentRedelivery(boolean enabled) {
super.setIntentRedelivery(enabled);
System.out.println("setIntentRedelivery");
}
@Override
protected void onHandleIntent(Intent intent) {
//Intent是从Activity发过来的,携带识别参数,根据参数不同执行不同的任务
String action = intent.getExtras().getString("param");
if (action.equals("oper1")) {
System.out.println("Operation1");
}else if (action.equals("oper2")) {
System.out.println("Operation2");
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onDestroy() {
System.out.println("onDestroy");
super.onDestroy();
}
}
在Activity里面使用
public class TestActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//可以启动多次,每启动一次,就会新建一个work thread,但IntentService的实例始终只有一个
//Operation 1
Intent startServiceIntent = new Intent("com.test.intentservice");
Bundle bundle = new Bundle();
bundle.putString("param", "oper1");
startServiceIntent.putExtras(bundle);
startService(startServiceIntent);
//Operation 2
Intent startServiceIntent2 = new Intent("com.test.intentservice");
Bundle bundle2 = new Bundle();
bundle2.putString("param", "oper2");
startServiceIntent2.putExtras(bundle2);
startService(startServiceIntent2);
}
}
在AndroidManifest.xml里面进行注册:
- 3)、总结
- 1、可用于执行后台耗时的任务,任务执行后会自动停止。
- 2、具有高优先级,适合高优先级的后台任务,且不容易被系统杀死。
- 3、可以多次启动,每个耗时操作都会以工作队列的方式在IntentService的onHandleIntent回调方法中执行
三、Glide 生命周期管理
//用于缓存fragment
final Map pendingSupportRequestManagerFragments = new HashMap<>();
@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
//尝试通过tag,从FragmentManager中获取绑定的fragment
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
//尝试冲Map缓存中获取fragment
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
//添加fragment到缓存map中
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
//把fragment从map中移出,原理是Handler里面的消息是一个队列,obtainMessage放在commitAllowingStateLoss 添加的事务之后,
//可以是Handler先处理绑定Fragment的事务在处理移出Fragment的事务。从而保证不多次创建Fragment。
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
从上面代码可见看出避免Glide#with()多次调用,多次创建fragment。使用pendingSupportRequestManagerFragments
Map缓存的作用是:
Glide.with(context).load(url).into(mImageView);
Glide.with(context).load(url).into(mImageView);
Glide.with(context).load(url).into(mImageView);
当出现上面情况的时候,我们可以知道当执行commitAllowingStateLoss
让Fragment
和FragmentManager
绑定的时候,实际上是通过Handler#post()
发送事务进行绑定,过程如下:
BackStackRecord继承FragmentTransaction,然后在BackStackRecord处理事务。BackStackRecord#commitAllowingStateLoss
然后调用BackStackRecord#commitInternal
方法
@Override
public int commitAllowingStateLoss() {
return commitInternal(true);
}
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(TAG, "Commit: " + this);
LogWriter logw = new LogWriter(TAG);
PrintWriter pw = new PrintWriter(logw);
dump(" ", pw);
pw.close();
}
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex();
} else {
mIndex = -1;
}
//调用FragmentManager,添加事务到队列中
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
然后调用FragmentManager#enqueueAction
,最后调用FragmentManager#scheduleCommit
方法,让后通过Hander的发送和处理事务。
void enqueueAction(@NonNull OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
if (mHost == null) {
if (mDestroyed) {
throw new IllegalStateException("FragmentManager has been destroyed");
} else {
throw new IllegalStateException("FragmentManager has not been attached to a "
+ "host.");
}
}
checkStateLoss();
}
synchronized (mPendingActions) {
if (mHost == null) {
if (allowStateLoss) {
// This FragmentManager isn't attached, so drop the entire transaction.
return;
}
throw new IllegalStateException("Activity has been destroyed");
}
mPendingActions.add(action);
//提交事务
scheduleCommit();
}
}
void scheduleCommit() {
synchronized (mPendingActions) {
boolean postponeReady =
mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
boolean pendingReady = mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
mHost.getHandler().removeCallbacks(mExecCommit);
//通过Hander发送消息处理事务
mHost.getHandler().post(mExecCommit);
updateOnBackPressedCallbackEnabled();
}
}
}
当Hanler处理好Fragment和FragmentManager绑定。就通过收到Handler的消息(Handler#ID_REMOVE_SUPPORT_FRAGMENT_MANAGER
)来释放Map的内存,避免内存泄露。
@Override
public boolean handleMessage(Message message) {
boolean handled = true;
Object removed = null;
Object key = null;
switch (message.what) {
case ID_REMOVE_FRAGMENT_MANAGER:
//移出fragment
android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
key = fm;
removed = pendingRequestManagerFragments.remove(fm);
break;
case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
FragmentManager supportFm = (FragmentManager) message.obj;
key = supportFm;
//释放内存
removed = pendingSupportRequestManagerFragments.remove(supportFm);
break;
default:
handled = false;
break;
}
if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
}
return handled;
}