日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

android startanimation 回调,ScheduledThreadPoolExecutor执行莫名停止问题Android几个动画回调运行线程...

發(fā)布時間:2023/12/2 Android 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android startanimation 回调,ScheduledThreadPoolExecutor执行莫名停止问题Android几个动画回调运行线程... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文記錄兩個問題:

ScheduleThreadPoolExecutor莫名停止執(zhí)行。Animation和Animator兩個動畫回調(diào)監(jiān)聽 運(yùn)行在哪個線程。

一:ScheduleThreadPoolExecutor問題:

ScheduledThreadPoolExecutor中scheduleWithFixedDelay(command, initialDelay, delay, unit)這個方法。我們會實現(xiàn)command這個Runnable參數(shù)。

問題:

當(dāng)我們實現(xiàn)run()方法時,如果run()方法內(nèi)運(yùn)行時報錯,那么ScheduleThreadPoolExecutor會自動停止,并且app不會崩潰,logcat也不會打印錯誤日志。。。

解決方法:

在api中也介紹了,如果希望executor繼續(xù)運(yùn)行下去,那么就必須將報錯try catch掉。否則報錯線程池將停止繼續(xù)運(yùn)行。

二:Animation和Animator兩個動畫回調(diào)監(jiān)聽 運(yùn)行在哪個線程:

setAnimationListener(new ...{

onAnimationStart()

onAnimationRepeat()

onAnimationEnd()

})

1.Animation:View動畫

先找到這個回調(diào)調(diào)用的地方:在Animation類中,源碼:

/**

* Sets the handler used to invoke listeners.

*

* @hide

*/

public void setListenerHandler(Handler handler) {

if (mListenerHandler == null) {

mOnStart = new Runnable() {

public void run() {

if (mListener != null) {

mListener.onAnimationStart(Animation.this);

}

}

};

mOnRepeat = new Runnable() {

public void run() {

if (mListener != null) {

mListener.onAnimationRepeat(Animation.this);

}

}

};

mOnEnd = new Runnable() {

public void run() {

if (mListener != null) {

mListener.onAnimationEnd(Animation.this);

}

}

};

}

mListenerHandler = handler;

}可以看見回調(diào)方法被放到了Runnable里,那么講道理,這個會通過handler處理。那么就找mOnStart。。這幾個參數(shù)在哪里被調(diào)用了:

private void fireAnimationStart() {

if (mListener != null) {

if (mListenerHandler == null) mListener.onAnimationStart(this);

else mListenerHandler.postAtFrontOfQueue(mOnStart);

}

}

恩,將Runnable傳遞給mListenerHanlder去處理了。那么mListenerHandler這個handler在哪里被賦值的呢?哦。。在上面方法最后mListenerHandler = handler;

最后找到,在View類中:其中有一句代碼:

if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);

A Handler supplied by a view's {@link android.view.ViewRootImpl}. This?handler can be used to pump events in the UI events queue.

這是AttachInfo類中mHandler的注釋??梢钥吹绞枪躑I的handler。那肯定是在主線程中執(zhí)行回調(diào)方法了。

結(jié)論:Animation回調(diào)方法一定是在主線程中了。

2.Animator:屬性動畫ValueAnimator等

同樣,看listener在源碼哪里被調(diào)用了:

private void notifyStartListeners() {

if (mListeners != null && !mStartListenersCalled) {

ArrayList tmpListeners =

(ArrayList) mListeners.clone();

int numListeners = tmpListeners.size();

for (int i = 0; i < numListeners; ++i) {

tmpListeners.get(i).onAnimationStart(this);

}

}

mStartListenersCalled = true;

}private void start(boolean playBackwards) {

if (Looper.myLooper() == null) {

throw new AndroidRuntimeException("Animators may only be run on Looper threads");

}

...

if (mStartDelay == 0) {

...

notifyStartListeners();

}

animationHandler.start();

} ? ? ? Animator的start()會調(diào)用上面start(boolean)方法,調(diào)用notifyStartListeners()方法。這么看來,意思是Animator.start()方法在哪個線程里執(zhí)行,回調(diào)就在哪個線程中。一會兒咱們測試一下是不是。注意上面一句代碼:AndroidRuntimeException("Animators may only be run on Looper threads");看來Animator是可以在子線程中運(yùn)行,但是該線程必須有l(wèi)ooper!好咧,搞個代碼測試下!

final ValueAnimator va = ObjectAnimator.ofFloat(0, 1);

va.setDuration(5000);

va.addUpdateListener(new AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

Log.e("TAG", "onAnimationUpdate"

+ Thread.currentThread().getName());

// start在什么線程回調(diào)就在什么線程

}

});

va.addListener(new AnimatorListener() {

@Override

public void onAnimationStart(Animator animation) {

Log.e("TAG", "onAnimationStart"

+ Thread.currentThread().getName());

}

@Override

public void onAnimationRepeat(Animator animation) {

Log.e("TAG", "onAnimationRepeat"

+ Thread.currentThread().getName());

}

@Override

public void onAnimationEnd(Animator animation) {

Log.e("TAG", "onAnimationEnd"

+ Thread.currentThread().getName());

}

@Override

public void onAnimationCancel(Animator animation) {

Log.e("TAG", "onAnimationCancel"

+ Thread.currentThread().getName());

}

});

//va.start(); new Thread("hah") {public void run() {Looper.prepare();va.start();Looper.loop();};}.start();

上面代碼測試后,結(jié)果果然是當(dāng)start()在主線程中調(diào)用,那么回調(diào)方法全部都在主線程。如果在“hah”這個子線程中調(diào)用,那么回調(diào)方法都在“hah”子線程中。

結(jié)論:Animator的start()方法在哪個線程中調(diào)用,回調(diào)就在哪個線程中。注意:子線程需要有l(wèi)ooper。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的android startanimation 回调,ScheduledThreadPoolExecutor执行莫名停止问题Android几个动画回调运行线程...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。