最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android異步回調(diào)中的UI同步性問(wèn)題分析

 更新時(shí)間:2016年06月01日 16:27:11   作者:Windstep  
這篇文章主要為大家詳細(xì)分析了Android異步回調(diào)中的UI同步性問(wèn)題,感興趣的小伙伴們可以參考一下

Android程序編碼過(guò)程中,回調(diào)無(wú)處不在。從最常見(jiàn)的Activity生命周期回調(diào)開(kāi)始,到BroadcastReceiver、Service以及Sqlite等。Activity、BroadcastReceiver和Service這些基本組件的回調(diào)路徑和過(guò)程也就是通常意義上所謂的“生命周期”。同時(shí),在處理具體的業(yè)務(wù)邏輯時(shí),常常設(shè)計(jì)到不同線(xiàn)程之間的通信,如下載圖片完成后通知 UI線(xiàn)程更新UI,凡此類(lèi)場(chǎng)景,無(wú)論使用哪一種具體的線(xiàn)程間通信方式(Handler/Message、Handler/post、基于接口的回調(diào)、基于多對(duì)多的觀察者模式如EventBus等),其本質(zhì)上都是基于“回調(diào)”。在實(shí)際編碼過(guò)程中,凡涉及到不同線(xiàn)程之間的通信,本質(zhì)上更是屬于“異步回調(diào)”。當(dāng)需要在“異步回調(diào)”中修改UI時(shí),此時(shí)需要特別注意UI同步性問(wèn)題。

為了便于問(wèn)題的闡述,在此先對(duì)“Android異步回調(diào)UI同步性問(wèn)題”進(jìn)行如下界定:當(dāng)異步回調(diào)執(zhí)行時(shí)(稱(chēng)之為“異步回調(diào)執(zhí)行點(diǎn)”),當(dāng)前UI界面上的元素與最初生成此異步回調(diào)的調(diào)用器開(kāi)始執(zhí)行時(shí)(稱(chēng)之為“異步回調(diào)生成點(diǎn)”)的UI元素已經(jīng)存在不一致,不一致不僅包括UI元素可能的界面變化、可能的內(nèi)容變化,也包括“異步回調(diào)執(zhí)行點(diǎn)”和“異步回調(diào)生成點(diǎn)”時(shí)的UI元素中的某一特性的表征量(如某一具有表征當(dāng)前UI元素的字段值)相關(guān),即使UI元素界面和內(nèi)容都尚未發(fā)生變化。

編碼過(guò)程中,“Android異步回調(diào)UI同步性問(wèn)題”經(jīng)常存在,有時(shí)候稍不注意會(huì)產(chǎn)生一些看起來(lái)難以理解的bug,并由于異步特性的存在,此類(lèi)bug還具有一定的隨機(jī)性。有時(shí)候由于一些需求的復(fù)雜性,此類(lèi)bug隱蔽性很強(qiáng),也容易被忽略。至少到目前為止,在實(shí)際開(kāi)發(fā)中,本人遇到此類(lèi)問(wèn)題已有數(shù)個(gè)。

純文字的描述可能不太好理解,下面以一個(gè)很常用的Android-Universal-Image-Loader為例,簡(jiǎn)單舉例一個(gè)潛在存在的“Android異步回調(diào)UI同步性問(wèn)題”。

ListView Item View中有ImageView,通過(guò)Android-Universal-Image-Loader去加載顯示,圖片加載完成后需要做一些邏輯處理(如隱藏圖片加載進(jìn)度條等..),通常代碼如下:

ImageLoader.getInstance().loadImage(imageUrl, new ImageLoadingListener() {
        
 @Override
 public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
  if (loadedImage != null) {
   imageView.setImageBitmap(loadedImage);
   // 其他業(yè)務(wù)邏輯處理..
  }
 }

 @Override
 public void onLoadingStarted(String imageUri, View view) {
  
 }

 @Override
 public void onLoadingCancelled(String arg0, View arg1) {
  
 }

 @Override
 public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
  
 }
});

初看上去,代碼邏輯好像也沒(méi)什么問(wèn)題,網(wǎng)上大部分人也是這么寫(xiě)的。當(dāng)較慢滑動(dòng)ListView時(shí),或在平時(shí)正常使用時(shí),也沒(méi)有什么問(wèn)題。但是此處的代碼邏輯真的嚴(yán)密嗎?

ListView的getView復(fù)用特性,大家也都熟知。對(duì)于之前遇到的“圖片錯(cuò)位/先顯示之前的圖片后再被正確的圖片覆蓋掉”,此類(lèi)現(xiàn)象也都知道如何解決(在getView邏輯開(kāi)始處理處將ImageView設(shè)置成最先的默認(rèn)圖片,其他UI元素類(lèi)似處理),基本上也不會(huì)再有“圖片錯(cuò)位/先顯示之前的圖片后再被正確的圖片覆蓋掉”這類(lèi)現(xiàn)象了。實(shí)際上,當(dāng)網(wǎng)速條件一般,且loadImage大致與上述代碼所示,在ListView中快速滑動(dòng)列表,幾屏后,不出意外,會(huì)發(fā)現(xiàn)“圖片錯(cuò)位/先顯示之前的圖片后再被正確的圖片覆蓋掉”此問(wèn)題依然存在。

此時(shí)問(wèn)題出現(xiàn)的原因不在于getView本身,因?yàn)間etView邏輯開(kāi)始時(shí)已經(jīng)將ImageView重置為默認(rèn)圖片,而在于“Android異步回調(diào)UI同步性問(wèn)題”。由于ViewHolder的不斷復(fù)用,網(wǎng)速一般時(shí)快速滑動(dòng)幾屏后,onLoadingComplete的異步回調(diào)執(zhí)行時(shí)與當(dāng)前UI元素已經(jīng)存在不一致,簡(jiǎn)單點(diǎn)理解,ImageView被復(fù)用了ImageView position 0,ImageView position 11, ImageView position 21,此時(shí)滑動(dòng)停止,onLoadingComplete的異步回調(diào)執(zhí)行時(shí)ImageView已經(jīng)是最后一次的ImageView position 21,而onLoadingComplete的異步回調(diào)可能被執(zhí)行數(shù)次(ImageView position 0,ImageView position 11, ImageView position 21,且順序還取決于異步中的具體處理和網(wǎng)絡(luò)環(huán)境等),于是問(wèn)題發(fā)生了。

解決方案:
抓住”UI元素中的某一特性的表征量“,在異步回調(diào)中通過(guò)比較“異步回調(diào)生成點(diǎn)”和“異步回調(diào)執(zhí)行點(diǎn)”此特征變量的值直接作出邏輯上的處理。

public class HardRefSimpleImageLoadingListener implements ImageLoadingListener {

 public int identifier;

 public HardRefSimpleImageLoadingListener() {
 }

 public HardRefSimpleImageLoadingListener(int identifier) {
  this.identifier = identifier;
 }

 @Override
 public void onLoadingCancelled(String arg0, View arg1) {

 }

 @Override
 public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {

 }

 @Override
 public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {

 }

 @Override
 public void onLoadingStarted(String arg0, View view) {
 
 }
}

ImageLoader.getInstance().loadImage(imageUrl, new HardRefSimpleImageLoadingListener(did) {
 @Override
 public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
  if (loadedImage != null) {
   if (identifier != did) {
    return;
   }
   imageView.setImageBitmap(loadedImage);
   // 其他業(yè)務(wù)邏輯處理..
  }
 }
});


總之,凡此類(lèi)“Android異步回調(diào)UI同步性問(wèn)題”,最好都通過(guò)比較“異步回調(diào)生成點(diǎn)”“異步回調(diào)執(zhí)行點(diǎn)”特征變量的值去針對(duì)性的做邏輯處理,以免出現(xiàn)不必要的Bug,是非常必要且有效的手段。

 原文地址:http://www.cnblogs.com/lwbqqyumidi/p/4110377.html

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

伊宁县| 百色市| 胶南市| 赫章县| 石嘴山市| 大化| 兴仁县| 绥江县| 都兰县| 扬州市| 灵璧县| 河南省| 布尔津县| 荃湾区| 威远县| 兴文县| 垦利县| 比如县| 汉阴县| 老河口市| 绍兴市| 察隅县| 九龙坡区| 开阳县| 南涧| 锡林郭勒盟| 荥经县| 丹棱县| 芜湖市| 金平| 花莲市| 贵阳市| 乌鲁木齐市| 三台县| 法库县| 阳江市| 瓦房店市| 通江县| 左云县| 汉源县| 香港|