Android筆記總結(jié)

圖片發(fā)自簡書App

這是自己在項(xiàng)目當(dāng)中踩過的坑而總結(jié)整理的筆記葱椭,僅供自己催植。署名android developer


基礎(chǔ)知識

此部分包含android相關(guān)的基礎(chǔ)部分橡羞,而且是容易忽視的基礎(chǔ),平時(shí)很少用到但用時(shí)卻不知道的砸民。

1 Android launchMode

Task是一個具有棧結(jié)構(gòu)的對象,一個Task可以管理多個Activity奋救,啟動一個應(yīng)用岭参,也就創(chuàng)建一個與之對應(yīng)的task。Activity一共有以下四種launchMode:

  • standard
  • singleTop
  • singleTask
  • singleInstance

[圖片上傳失敗...(image-a1184e-1556638375279)]
[圖片上傳失敗...(image-398128-1556638375279)]
[圖片上傳失敗...(image-eea1a2-1556638375279)]
每次跳轉(zhuǎn)系統(tǒng)都會在task中生成一個新的FirstActivity實(shí)例尝艘,并且放于棧結(jié)構(gòu)的頂部演侯,當(dāng)我們按下后退鍵時(shí),才能看到原來的FirstActivity實(shí)例背亥。standard啟動模式秒际,不管有沒有已存在的實(shí)例,都生成新的實(shí)例狡汉。

[圖片上傳失敗...(image-d1ace4-1556638375279)]
[圖片上傳失敗...(image-3ddbdc-1556638375279)]
[圖片上傳失敗...(image-9b51ba-1556638375279)]
三個序列號是相同的娄徊,也就是說使用的都是同一個FirstActivity實(shí)例;如果按一下后退鍵盾戴,程序立即退出寄锐,說明當(dāng)前棧結(jié)構(gòu)中只有一個Activity實(shí)例。跳轉(zhuǎn)時(shí)系統(tǒng)會先在棧結(jié)構(gòu)中尋找是否有一個FirstActivity實(shí)例正位于棧頂,如果有則不再生成新的橄仆,而是直接使用剩膘。
singleTop啟動模式,如果發(fā)現(xiàn)有對應(yīng)的Activity實(shí)例正位于棧頂盆顾,則重復(fù)利用援雇,不再生成新的實(shí)例。

singleTask模式椎扬,如果發(fā)現(xiàn)有對應(yīng)的Activity實(shí)例惫搏,則使此Activity實(shí)例之上的其他Activity實(shí)例統(tǒng)統(tǒng)出棧,使此Activity實(shí)例成為棧頂對象蚕涤,顯示到幕前筐赔。

singleInstance啟動模式可能是最復(fù)雜的一種模式,為了幫助大家理解揖铜,我舉一個例子茴丰,假如我們有一個share應(yīng)用,其中的ShareActivity是入口Activity天吓,也是可供其他應(yīng)用調(diào)用的Activity贿肩,我們把這個Activity的啟動模式設(shè)置為singleInstance,然后在其他應(yīng)用中調(diào)用龄寞。我們編輯ShareActivity的配置:

<activity android:name=".ShareActivity" android:launchMode="singleInstance">  
    <intent-filter>  
        <action android:name="android.intent.action.MAIN" />  
        <category android:name="android.intent.category.LAUNCHER" />  
    </intent-filter>  
    <intent-filter>  
        <action android:name="android.intent.action.SINGLE_INSTANCE_SHARE" />  
        <category android:name="android.intent.category.DEFAULT" />  
    </intent-filter>  
</activity>  

然后我們在其他應(yīng)用中這樣啟動該Activity:

Intent intent = new Intent("android.intent.action.SINGLE_INSTANCE_SHARE");  
startActivity(intent);  

一般的登陸界面LoginActivity設(shè)計(jì)為

android:launchMode="singleTask"

Flags模式:

//如果activity在task存在汰规,拿到最頂端,不會啟動新的Activity
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
//如果activity在task存在,將Activity之上的所有Activity結(jié)束掉
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//默認(rèn)的跳轉(zhuǎn)類型,將Activity放到一個新的Task中
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//如果Activity已經(jīng)運(yùn)行到了Task物邑,再次跳轉(zhuǎn)不會在運(yùn)行這個Activity
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

2 Spinner

  • 獲取默認(rèn)值:Spinner.setSelection(int positon, boole anitme);
    在做二級聯(lián)動時(shí)此方法屬于同步方法溜哮,需要開啟異步任務(wù)。
Handler handler = new Handler();
    handler.post(new Runnable() {
        @Override
        public void run() {
            Spinner.setSelection(0, true);
        }
});

或者做一個延時(shí)操作色解。

3 ScrollView

  • 滾動:
Handler handler = new Handler();
handler.post(new Runnable() {
     @Override
     public void run() {
          // ScrollView.FOCUS_DOWN 底部
          // ScrollView.FOCUS_UP 頂部
          mScrollView.fullScroll(ScrollView.FOCUS_DOWN); 
     }
});

4 Android Studio支持java8

第一步 配置JAVA8

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

第二步 使用jack鏈

defaultConfig {
    jackOptions {
        enabled true
    }
}

5 軟盤

保持狀態(tài)欄不被擠掉

android:windowSoftInputMode="stateVisible|adjustResize|stateHidden"

適合頂部有輸入框

android:windowSoftInputMode="adjustPan|stateHidden"

6 屏幕旋轉(zhuǎn)

在需要旋轉(zhuǎn)的界面Activity注冊清單中配置

android:configChanges="keyboardHidden|orientation|screenSize"

再在Activity中重寫

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        // do something
    } else {
        // do something
    }
}

7 ScrollView嵌套列表解決焦點(diǎn)停留在列表上的問題

在Scrollview第一層子View上設(shè)置屬性

android:descendantFocusability="blocksDescendants"

8 View超出容器

第一步設(shè)置View的margin值為負(fù)數(shù)

android:layout_margint="-10dp"

第二步給父容器設(shè)置屬性 false不裁剪

android:clipChildren="false"

9 防止頁面打開時(shí)彈出軟盤

添加屬性

android:focusable="true"
android:focusableInTouchMode="true"

10 Formatter.formatFileSize(Context context, long sizeBytes)

格式化文件大小茂嗓,將字節(jié)數(shù)據(jù)格式化為 B、KB科阎、M 等單位的相應(yīng)數(shù)據(jù)述吸。context 參數(shù)用于判斷返回結(jié)果的字符串順序,right-to-left 還是 left-to-right 形式的锣笨。這個工具類免去我們自己轉(zhuǎn)化計(jì)算的過程蝌矛,非常方便,特別適用于應(yīng)用內(nèi)文件下載的類似場景票唆。

11 TypedValue.applyDimension(int unit, float value, DisplayMetrics metrics)

  • COMPLEX_UNIT_PX
  • COMPLEX_UNIT_DIP
  • COMPLEX_UNIT_PT
  • COMPLEX_UNIT_SP

將指定單位的尺寸數(shù)據(jù)按照當(dāng)前設(shè)備屏幕信息轉(zhuǎn)化為相應(yīng)的像素值朴读。其中,TypedValue 為第一個參數(shù)提供了常用的單位值

12 Space

Space 是一個用于創(chuàng)建視圖之間空隙的輕量級 View走趋。在onDraw()方法中不執(zhí)行任何繪制衅金,所以android:background屬性對他來說不起作用。通常我們使用 View 創(chuàng)建視圖間的空隙,在不考慮背景色的情況下氮唯,Space其實(shí)效率更高鉴吹。注意,由于是 API 14 引入的控件惩琉,如果需要向前兼容的話豆励,需要使用到 support v4 包。

13 view.performClick()

自動調(diào)用View點(diǎn)擊事件瞒渠。通常按鈕等控件只有在用戶點(diǎn)擊時(shí)才能觸發(fā)其點(diǎn)擊事件良蒸,該方法可以由某些特殊條件觸發(fā)模擬用戶點(diǎn)擊行為。類似的還有performLongClick()方法伍玖。

14 Log.getStackTraceString(Throwable tr)

Log類提供的一個公共靜態(tài)方法嫩痰,與常見的Log.i()等方法打印日志到logcat控制臺不同的是,該方法從Throwable對象中獲取錯誤信息窍箍,并以字符串的形式返回串纺。當(dāng)你需要做錯誤信息的數(shù)據(jù)持久化,比如保存至本地存儲卡中或者上傳至服務(wù)器時(shí)椰棘,利用這個方法就非常方便纺棺。

15 Linkify.addLinks()

我們知道對于TextView文本控件中的內(nèi)容,通過android:autoLink屬性可以為其添加諸如web邪狞、phone 等固定模版的超鏈接點(diǎn)擊事件祷蝌。但畢竟系統(tǒng)模版有限,而利用Linkify.addLinks() 方法可以添加一些應(yīng)用內(nèi)自定義模版外恕,比如新浪微博中的 "@XXX" 格式的超鏈接跳轉(zhuǎn)等杆逗,都可以通過自定義正則表達(dá)式來匹配處理乡翅。

16 禁止截屏

getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE)

設(shè)置安全窗口鳞疲,禁用系統(tǒng)截屏。防止App中的一些界面被截屏蠕蚜,并顯示在其他設(shè)備中造成信息泄漏尚洽。
比如支付寶App的“向商家付款”的包含付款二維碼的界面。(補(bǔ)充說明一點(diǎn)靶累,微信付款界面不是這么做的腺毫,采用的是在onResume()生命周期方法中實(shí)時(shí)刷新付款二維碼,與支付寶在安全方法采取的手段不同挣柬。)

17 攔截Bac 鍵,使App進(jìn)入后臺而不是關(guān)閉

@Override
public void onBackPressed() {
  Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
  launcherIntent.addCategory(Intent.CATEGORY_HOME);
  startActivity(launcherIntent);
}

使用Back鍵返回桌面,但不關(guān)閉當(dāng)前應(yīng)用舰褪,而是使之進(jìn)入后臺健提,就像按下Home鍵一樣。
這個技巧厲害了。通常為了防止出現(xiàn)用戶誤按Back鍵退出App的情況勃教,我們會在應(yīng)用首頁的Activity中監(jiān)聽返回鍵操作淤击,使用Toast弱提示甚至Dialog強(qiáng)提示的方式給到用戶一個再次確認(rèn)的操作,但無法阻止用戶通過返回鍵逐步關(guān)閉應(yīng)用故源。

然而污抬,如果用這個方法攔截 App 最后一個 Activity(常見為首頁界面),既沒有阻礙用戶操作(回到桌面)绳军,又沒有關(guān)閉掉我們的應(yīng)用(后臺運(yùn)行中)印机,間接提高 App 的存活時(shí)間,真乃暗度陳倉门驾。并且據(jù)我實(shí)驗(yàn)耳贬,微信、支付寶猎唁、微博等 App 都是這么做的咒劲,大家不妨一試。

另外其他幾種方法

  • finish(); 正常退出遵循android系統(tǒng)規(guī)則
  • android.os.Process.killProcess(android.os.Process.myPid());
  • System.exit(0); java退出機(jī)制
  • moveTaskToBack(true); 退出程序后臺苯胗纾活
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
        if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                ToastUtil.getInstace(getActivity()).show("再按一次退出程序");
                exitTime = System.currentTimeMillis();
            } else {
                finish();
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(0);
                moveTaskToBack(true);
            }
        }
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

18 縮略圖工具類ThumbnailUtils

縮略圖工具類腐魂,可以根據(jù)本地視頻文件源、Bitmap 對象生成縮略圖逐纬,常用的公共靜態(tài)方法為:

  • createVideoThumbnail(String filePath, int kind)
  • extractThumbnail(Bitmap source, int width, int height)

19 bitmap.extractAlpha()

從源bitmap中根據(jù)alpha獲取一個新的bitmap對象蛔屹。比較繞口,通常App中的Icon多數(shù)是純色透明像素背景組成豁生,利用這個方法可以對該圖的非透明區(qū)域著色兔毒,有多種使用場景,常見如Button的pressed狀態(tài)甸箱,View 的陰影狀態(tài)等育叁。舉個例子:

private static Bitmap getDropShadow(ImageView iv, Bitmap src, float radius, int color) {

    final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setColor(color);

    final int width = src.getWidth(), height = src.getHeight();
    final Bitmap dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    final Canvas canvas = new Canvas(dest);
    final Bitmap alpha = src.extractAlpha();
    canvas.drawBitmap(alpha, 0, 0, paint);

    final BlurMaskFilter filter = new BlurMaskFilter(radius, BlurMaskFilter.Blur.OUTER);
    paint.setMaskFilter(filter);
    canvas.drawBitmap(alpha, 0, 0, paint);
    iv.setImageBitmap(dest);

    return dest;
}

20 ArgbEvaluator

系統(tǒng)提供的一個TypeEvaluator,我們只需要提供兩個起始顏色值和一個分值芍殖,系統(tǒng)會通過特定的算法計(jì)算得出一個新的顏色中間值豪嗽。利用這個類,我們至少可以做兩件事情豌骏。

第一龟梦,用于屬性動畫中。由于其實(shí)現(xiàn)了TypeEvaluator接口窃躲,可以用來做自定義屬性動畫的求值器计贰,改變 View 的顯示狀態(tài)。比如:

int colorStart = ContextCompat.getColor(this, R.color.black);
int colorEnd = ContextCompat.getColor(this, R.color.green);
ValueAnimator valueAnimator = ValueAnimator
    .ofObject(new ArgbEvaluator(), colorStart, colorEnd)
    .setDuration(3000);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        textView.setTextColor((Integer) animation.getAnimatedValue());
    }
});
valueAnimator.start();

第二蒂窒,利用該類提供的顏色求值算法躁倒,配合ViewPager提供的滑動偏離值使用赎婚。這種場景常見于使用ViewPager實(shí)現(xiàn)的引導(dǎo)頁,其背景色隨著滑動距離動態(tài)改變樱溉;使用ViewPager實(shí)現(xiàn)的Tab樣式菜單頁面挣输,Tab 中文本內(nèi)容隨著滑動距離動態(tài)改變字體顏色(可以參考安卓版微信)。這兩種使用都使得ViewPager頁面切換過渡得很自然福贞,體驗(yàn)極佳撩嚼。如:

viewPager.addOnPageChangeListener(new OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        new ArgbEvaluator().evaluate(positionOffset, startColor, endColor);
    }

    @Override
    public void onPageSelected(int position) {

    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
});

另外,關(guān)于顏色差值的計(jì)算挖帘,Google Sample里有另一種算法完丽,可參考SlidingTabStrip.java文件源碼,核心方法內(nèi)容如下:

/**
 * Blend {@code color1} and {@code color2} using the given ratio.
 *
 * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend,
 *              0.0 will return {@code color2}.
 */
private static int blendColors(int color1, int color2, float ratio) {
    final float inverseRation = 1f - ratio;
    float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
    float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
    float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
    return Color.rgb((int) r, (int) g, (int) b);
}

21 android:weightSum

用于LinearLayout中拇舀,用于設(shè)置Childrenweight的總比重逻族。在LinearLayout的children中,我們經(jīng)常會使用android:layout_weight按比例分配容器布局的空間骄崩,但有時(shí)候不一定會分完聘鳞。以往,有些朋友可能會使用一個空 放在最后來達(dá)到末尾占位效果要拂。如果你知道這個屬性的話抠璃,就能少寫一些代碼。

22 android:descendantFocusability

用于ViewGroup中脱惰,解決作為ParentViewGroupChildren View之間的焦點(diǎn)占用問題搏嗡。最最常見的使用場景就是 list item 中含有一些點(diǎn)擊效果的控件,比如 Button拉一、CheckBox 等采盒,相信大家都遇到過。取值有三種蔚润,含義就不用再多說了:

  • afterDescendants viewgroup只有當(dāng)其子類控件不需要獲取焦點(diǎn)時(shí)才獲取焦點(diǎn)
  • beforeDescendants viewgroup會優(yōu)先其子類控件而獲取到焦點(diǎn)
  • blocksDescendants viewgroup會覆蓋子類控件而直接獲得焦點(diǎn)

23 android:duplicateParentState

是否將View自身的drawable state交給直接parent ViewGroup控制磅氨,值為boolean類型。比如有一個item布局抽碌, item中有一個button悍赢,如果點(diǎn)擊item layout時(shí),需要button呈現(xiàn)對應(yīng)的點(diǎn)擊效果货徙,就可以在button中用到這個屬性。不過皮胡,從設(shè)計(jì)的角度來講痴颊,這種場景還是比較少見的。知道有這個屬性就好屡贺,不推薦這種交互設(shè)計(jì)蠢棱。

24 android:fillViewport

ScrollView的一個屬性锌杀,用于設(shè)置內(nèi)容部分是否填滿屏幕,主要針對內(nèi)容不足以填滿屏幕的情況泻仙。

25 android:adjustViewBounds

使用ImageView時(shí)糕再,你可能會用android:scaleType屬性設(shè)置圖片縮放方式。殊不知玉转,android:adjustViewBounds屬性也能起到類似的效果突想。但要注意的是,后者需要至少指定ImageView寬高中的一個屬性究抓,或者maxHeight之類的猾担,然后另一個屬性隨之適配。這個屬性用在列表中較為合適刺下,比如App中的活動列表頁面绑嘹,圖片寬度設(shè)置為match_parent,然后高度設(shè)為wrap_content使其自適應(yīng)橘茉,這樣便能保證從服務(wù)獲取的高分辨率圖片在不同的屏幕中不被拉伸變形工腋。(備注:最好在項(xiàng)目資源文件中放置一個與網(wǎng)絡(luò)圖片相同尺寸的默認(rèn)圖,起到placeholder作用畅卓,避免圖片顯示前高度為 0 的較差體驗(yàn)夷蚊。)

26 Android動畫——布局動畫、轉(zhuǎn)場動畫

布局動畫的作用于ViewGroup髓介,執(zhí)行動畫效果的是內(nèi)部的子View惕鼓。布局動畫在android中可以通過LayoutAnimationLayoutTransition來實(shí)現(xiàn)。

  1. LayoutAnimation

LayoutAnimation實(shí)際上是一個View動畫唐础,用來控制子View顯示時(shí)的動畫效果箱歧。可以通過Java代碼或者Xml文件來定義LayoutAnimation動畫一膨。
使用java代碼:

private void setLayoutAnimation() {
    Animation animation = AnimationUtils.loadAnimation(this, R.anim.layout_item_anim_set);
    LayoutAnimationController controller = new LayoutAnimationController(animation);
    controller.setDelay(0.5f);
    controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
    mListView.setLayoutAnimation(controller);
}

使用xml:

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/layout_item_anim_set"
    android:animationOrder="normal"
    android:delay="0.5">
</layoutAnimation>

ViewGroup所在布局中調(diào)用:

android:layoutAnimation="@anim/layout_anim"
  1. LayoutTransition
    LayoutTransition用于在ViewGroup中有子View添加呀邢、刪除、隱藏豹绪、顯示時(shí)所有子View動畫效果价淌。LayoutTransition有5中動畫變化形式
  • LayoutTransition.APPEARING:子View添加到容器中時(shí)的動畫效果
  • LayoutTransition.CHANGE_APPEARING:子View添加到容器中時(shí),其他子View位置改變的動畫效果
  • LayoutTransition.DISAPPEARING:子View被移除時(shí)的動畫效果
  • LayoutTransition.CHANGE_DISAPPEARING:子View被移除時(shí)瞒津,其他子View的動畫效果
  • LayoutTransition.CHANGING:子View在容器中位置變化時(shí)其他子View的動畫效果

使用默認(rèn)的動畫樣式:
只需要在使用的LinearLayout蝉衣、FrameLayoutRelativeLayout等ViewGroup容器的布局文件中添加android:animateLayoutChanges="true"即可巷蚪,系統(tǒng)會使用默認(rèn)的LayoutTransition來實(shí)現(xiàn)子View添加病毡、刪除或變化是的動畫效果。

27 Handler

  1. 定義
    Handler允許您發(fā)送和處理MessageRunnable與線程的MessageQueue關(guān)聯(lián)的對象屁柏。每個Handler實(shí)例與單個線程和該線程的MessageQueue相關(guān)聯(lián)啦膜。當(dāng)你創(chuàng)建一個新的Handler時(shí)有送,它綁定到線程/正在創(chuàng)建它的線程的消息隊(duì)列 - 從那時(shí)起,它會將消息和可運(yùn)行文件傳遞到該消息隊(duì)列并執(zhí)行他們從消息隊(duì)列中出來僧家。
  2. 處理程序有兩個主要用途
    (1)調(diào)度MessageRunnable將在未來的某個時(shí)候執(zhí)行;
    (2)入隊(duì)在不同于你自己的線程上執(zhí)行的動作雀摘。
private static class MessageHandler extends Handler {
    WeakReference<ImageLoadActivity> reference;

    MessageHandler(ImageLoadActivity activity) {
        reference = new WeakReference<>(activity);
    }

    // 處理消息
    @Override
    public void handleMessage(android.os.Message msg) {
        final ImageLoadActivity activity = reference.get();
        switch (msg.what) {
            case 0:
                Toast.makeText(activity, R.string.clear, Toast.LENGTH_LONG).show();
                break;

        }
        super.handleMessage(msg);
    }
}
// 創(chuàng)建
MessageHandler handler = new MessageHandler(this);
// 發(fā)送消息
new Thread(() -> {
    Glide.get(this).clearDiskCache();  // 清理磁盤緩存
    handler.sendEmptyMessage(0);
}).start();

28 Looper

  1. 定義
    用于為線程運(yùn)行消息循環(huán)的類。 線程默認(rèn)情況下沒有與他們相關(guān)聯(lián)的消息循環(huán); 創(chuàng)建一個八拱,調(diào)用Looper.prepare()在線程中運(yùn)行循環(huán)阵赠,然后調(diào)用Looper.loop()讓它處理消息,直到循環(huán)停止乘粒。大多數(shù)與消息循環(huán)的交互是通過的Handler類豌注。
class LooperThread extends Thread {
    Handler mHandler;

    public void run() {
        Looper.prepare();
        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                // process incoming messages here
            }
        };
        Looper.loop();
    }
}
  1. Looper主要作用:
    1、與當(dāng)前線程綁定灯萍,保證一個線程只會有一個Looper實(shí)例轧铁,同時(shí)一個Looper實(shí)例也只有一個MessageQueue。
    2旦棉、loop()方法齿风,不斷從MessageQueue中去取消息,交給消息的target屬性的dispatchMessage去處理绑洛。
    好了救斑,我們的異步消息處理線程已經(jīng)有了消息隊(duì)列(MessageQueue),也有了在無限循環(huán)體中取出消息的哥們真屯,現(xiàn)在缺的就是發(fā)送消息的對象了脸候,于是乎:Handler登場了。

29 Message

  1. 定義
    定義一個包含可以是描述和任意數(shù)據(jù)對象的消息發(fā)送到Handler绑蔫。 這個對象包含兩個額外的int字段和一個
    額外的object字段允許您在許多情況下不進(jìn)行分配运沦。雖然Message的構(gòu)造函數(shù)是公開的,但最好的方式是獲取其中之一是調(diào)用Message.obtain()或其中一個Handler.obtainMessage()方法配深,這將拉他們來自一個循環(huán)再造的物體池携添。

  2. 問題
    2.1 一個線程是否只有一個Looper?
    2.2 如何保證一個線程只有一個Looper篓叶?

30 android子線程更新UI

android提供以下幾種方法在主線程更新ui

  1. Activity.runOnUiThread(Runnable)
  2. View.post(Runnable)
  3. View.postDelayed(Runnable, long)
  4. Handler

31 關(guān)于Handler,Looper,Message總結(jié)

  1. 首先Looper.prepare()在本線程中保存一個Looper實(shí)例烈掠,然后該實(shí)例中保存一個MessageQueue對象;因?yàn)長ooper.prepare()在一個線程中只能調(diào)用一次缸托,所以MessageQueue在一個線程中只會存在一個左敌。
  2. Looper.loop()會讓當(dāng)前線程進(jìn)入一個無限循環(huán),不端從MessageQueue的實(shí)例中讀取消息嗦董,然后回調(diào)msg.target.dispatchMessage(msg)方法母谎。
  3. Handler的構(gòu)造方法,會首先得到當(dāng)前線程中保存的Looper實(shí)例京革,進(jìn)而與Looper實(shí)例中的MessageQueue想關(guān)聯(lián)奇唤。
  4. Handler的sendMessage方法,會給msg的target賦值為handler自身匹摇,然后加入MessageQueue中咬扇。
  5. 在構(gòu)造Handler實(shí)例時(shí),我們會重寫handleMessage方法廊勃,也就是msg.target.dispatchMessage(msg)最終調(diào)用的方法懈贺。
  6. 好了,總結(jié)完成坡垫,大家可能還會問梭灿,那么在Activity中,我們并沒有顯示的調(diào)用Looper.prepare()和Looper.loop()方法冰悠,為啥Handler可以成功創(chuàng)建呢堡妒,這是因?yàn)樵贏ctivity的啟動代碼中,已經(jīng)在當(dāng)前UI線程調(diào)用了Looper.prepare()和Looper.loop()方法
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末溉卓,一起剝皮案震驚了整個濱河市皮迟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌桑寨,老刑警劉巖伏尼,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尉尾,居然都是意外死亡爆阶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門沙咏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辨图,“玉大人,你說我怎么就攤上這事芭碍⊥揭郏” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵窖壕,是天一觀的道長忧勿。 經(jīng)常有香客問我,道長瞻讽,這世上最難降的妖魔是什么鸳吸? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮速勇,結(jié)果婚禮上晌砾,老公的妹妹穿的比我還像新娘。我一直安慰自己烦磁,他們只是感情好养匈,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布哼勇。 她就那樣靜靜地躺著,像睡著了一般呕乎。 火紅的嫁衣襯著肌膚如雪积担。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天猬仁,我揣著相機(jī)與錄音帝璧,去河邊找鬼。 笑死湿刽,一個胖子當(dāng)著我的面吹牛的烁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播诈闺,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼渴庆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了买雾?” 一聲冷哼從身側(cè)響起把曼,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎漓穿,沒想到半個月后嗤军,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晃危,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年叙赚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片僚饭。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡震叮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鳍鸵,到底是詐尸還是另有隱情苇瓣,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布偿乖,位于F島的核電站击罪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏贪薪。R本人自食惡果不足惜媳禁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望画切。 院中可真熱鬧竣稽,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拧烦,卻和暖如春忘闻,著一層夾襖步出監(jiān)牢的瞬間钝计,已是汗流浹背恋博。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留私恬,地道東北人债沮。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像本鸣,于是被迫代替她去往敵國和親疫衩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,777評論 25 707
  • Android Studio JNI流程首先在java代碼聲明本地方法 用到native關(guān)鍵字 本地方法不用去實(shí)現(xiàn)...
    MigrationUK閱讀 11,848評論 7 123
  • 1. ANR異常 Application No Response:應(yīng)用程序無響應(yīng)荣德。在主線程中闷煤,是不允許執(zhí)行耗時(shí)的操...
    JackChen1024閱讀 1,357評論 0 3
  • 簡單點(diǎn) 說話的方式簡單點(diǎn) 遞進(jìn)的情緒請省略 你又不是個演員 別設(shè)計(jì)那些情節(jié) 沒意見 我只想看看你怎么圓 你難過的太...
    滴答滴lowkey閱讀 414評論 0 0
  • 十二點(diǎn)終于忙完了,游戲也不想打了涮瞻,電影也不想看了鲤拿。對妹子都沒有興趣了,哈哈哈哈署咽。 1近顷,英語 課件一個小時(shí) 2,王者...
    Nick_k哥閱讀 175評論 2 0