音視頻開(kāi)發(fā)之旅(一)三種方式繪制圖片

在android開(kāi)發(fā)中我們最常使用的繪制圖片的方式就是ImageView玩徊,設(shè)置src。那么有沒(méi)有其他方案可以實(shí)現(xiàn)圖片的繪制吶炕舵?

三種方案

  1. 通過(guò)Imageview設(shè)置setImageBitmap
 final String path = Environment.getExternalStorageDirectory().getPath() + File.separator + "Pictures" + File.separator + "tmp.jpg";

        Bitmap bitmap = BitmapFactory.decodeFile(path);
        imageView.setImageBitmap(bitmap);
  1. 通過(guò)自定義View豪娜,定義Paint和讀取Bitmap吁津,然后在onDraw中用Canvas進(jìn)行drawBitamp
public class CustomView extends View {
    private Paint paint;
    private Bitmap bitmap;

    public CustomView(Context context) {
        this(context,null,0);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
    String path = Environment.getExternalStorageDirectory().getPath() + File.separator + "Pictures" + File.separator + "tmp.jpg";

        bitmap = BitmapFactory.decodeFile(path);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(bitmap!=null&&!bitmap.isRecycled()) {
            canvas.drawBitmap(bitmap, 0, 0, paint);
        }
    }
}
  1. 通過(guò)SurfaceView棚蓄,通過(guò)surfaceView的SufaceHolder,拿到到canvas然后進(jìn)行繪制碍脏。
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                if(holder == null){
                    return;
                }
                Paint paint = new Paint();
                paint.setAntiAlias(true);
//                                paint.setStyle(Paint.Style.STROKE);

       String path = Environment.getExternalStorageDirectory().getPath() + File.separator + "Pictures" + File.separator + "tmp.jpg";

                Bitmap bitmap1 = BitmapFactory.decodeFile(path);

                Canvas canvas = null;
                try {
                    canvas = holder.lockCanvas();
                    canvas.drawBitmap(bitmap1,0,0,paint);
                }catch (Exception e){
                    e.printStackTrace();
                } finally {
                    if(canvas!=null){
                        holder.unlockCanvasAndPost(canvas);
                    }

                }

                Log.d(TAG, "surfaceCreated: ");
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                Log.d(TAG, "surfaceChanged: format"+format+" w="+width+" h="+height);

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                Log.d(TAG, "surfaceDestroyed: ");

            }
        });

SurfaceView和View的優(yōu)劣對(duì)比以及使用場(chǎng)景

通過(guò)上面的例子我們可以看到SurfaceView和View的使用的方式的區(qū)別梭依,View可以直接可以通過(guò)ImageView封裝的API或者View的onDraw中拿到Canvas進(jìn)行繪制。而SurfaceView則通過(guò)SurfaceHolder也是拿到Canvas進(jìn)行繪制典尾。
下嗎我們來(lái)說(shuō)下SurfaceView和view的區(qū)別

一個(gè)窗口中的所有view役拴,共享一個(gè)window,對(duì)應(yīng)一個(gè)surface(繪圖表面)surface中有個(gè)Canvas钾埂,可用于繪制河闰,在WMS中只可見(jiàn)頂層的DecorView科平,在WMS中對(duì)應(yīng)WindowState,app請(qǐng)求刷新Surface時(shí)姜性,會(huì)在SurfaceFlinger內(nèi)部建立對(duì)應(yīng)的Layer瞪慧。

優(yōu)點(diǎn):

  1. 可以在子線(xiàn)程繪制--》適用于被動(dòng)頻繁刷新的界面,比如視頻播放或者游戲
  2. 刷新只會(huì)刷新自己而不會(huì)刷新其他view所有在的viewHierchy部念,避免造成整個(gè)viewHierchy刷新弃酌,性能會(huì)更好。
  3. 雙緩沖機(jī)制儡炼,避免閃爍妓湘,提升性能。
    缺點(diǎn):
  4. view的動(dòng)畫(huà)對(duì)sureface無(wú)效
    關(guān)閉window中所有view的硬件加速可以做到不透明的情況乌询。

如何使用:
Sureface.CallBack.
Sureface.getHolder
以及Sureface.lockCavas獲取到canvas進(jìn)行canvas操作然后sureface.unlockCavasAndPost進(jìn)行頁(yè)面的更新榜贴。

問(wèn)題:
為什么surfaceView不可見(jiàn)時(shí)會(huì)調(diào)用surfaceDestroyed,重新可見(jiàn)時(shí)有重新create楣责?
因?yàn)镾urfaceView的雙緩沖機(jī)制非常消耗內(nèi)存竣灌,Android規(guī)定SurfaceView不可見(jiàn)時(shí),會(huì)銷(xiāo)毀Surfaceview的SurfaceHolder秆麸,以達(dá)到節(jié)省系統(tǒng)資源的目的初嘹。

android10+存儲(chǔ)權(quán)限的獲取

在寫(xiě)該demo的時(shí)候,由于采用從外部存儲(chǔ)中讀取一種圖片進(jìn)行繪制沮趣,在獲取外部存儲(chǔ)權(quán)限的時(shí)候會(huì)遇到了麻煩屯烦,google對(duì)用戶(hù)權(quán)限的獲取越來(lái)越收斂,這是好事房铭。權(quán)限的授予用戶(hù)自己控制驻龟,在隱私安全上做了更好的保障。那么對(duì)于開(kāi)發(fā)者該如何獲取用戶(hù)的存儲(chǔ)權(quán)限吶缸匪?要做一下三步

  1. AndroidMainfest中注冊(cè)
  2. Application添加 android:requestLegacyExternalStorage="true"
  3. 通過(guò)AppOpsManager動(dòng)態(tài)的獲取

小結(jié)

通過(guò)本章翁狐,我們了解了繪制圖片根源都是在拿到Canvas然后在上面繪制bitmap。
可以通過(guò)ImageView提供的API凌蔬;可以通過(guò)自定義View露懒,在onDraw方法中進(jìn)行canvas的drawBitmap;也可以通過(guò)SurfaceView在onSurfaceCreate的時(shí)候通過(guò)surface的lockCanvas然后進(jìn)行canvas的drawbitmap砂心,最后在unlockCanvasAndPost到進(jìn)行繪制懈词。

SurfaceView和View最大的差異點(diǎn)在于,Surfaceview有自己?jiǎn)为?dú)的window辩诞,對(duì)應(yīng)WMS中有自己獨(dú)立的layer層坎弯,可以在子線(xiàn)程進(jìn)行繪制,刷新時(shí)不會(huì)影響所在的View樹(shù)結(jié)構(gòu)中的其他View,適用于被動(dòng)頻繁刷新的場(chǎng)景抠忘。相應(yīng)的劣勢(shì)是View的動(dòng)畫(huà)對(duì)Surfaceview無(wú)效撩炊,比如移動(dòng)縮放等,最明顯的表現(xiàn)就是有動(dòng)畫(huà)進(jìn)入或者滑動(dòng)退出有SurfaceView頁(yè)面時(shí)導(dǎo)致頁(yè)面透明褐桌。但是事實(shí)上在關(guān)閉View的硬件加速后是可以的衰抑。
關(guān)于Surfaceview的SurfaceHolder的生命周期,SurfaceView不可見(jiàn)時(shí)即進(jìn)行銷(xiāo)毀荧嵌,可見(jiàn)時(shí)再重新創(chuàng)建呛踊,原因在于SurfaceView采用了雙緩沖機(jī)制,做到了刷新是不閃爍啦撮。但是雙緩沖是比消耗內(nèi)存的谭网,所以android做了上述的策略。

Android10以上讀取sd卡的內(nèi)容等權(quán)限被google收斂赃春,首先要在AndroidManifest中注冊(cè)愉择,然后是使用前要?jiǎng)討B(tài)的獲取,在AndroidManifest的Application中也要加上

感謝閱讀织中。下一篇我們來(lái)分析學(xué)習(xí)下AudioTrack播放PCM锥涕,后續(xù)AudioRecord錄制PCM,歡迎關(guān)注交流狭吼。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末层坠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子刁笙,更是在濱河造成了極大的恐慌破花,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疲吸,死亡現(xiàn)場(chǎng)離奇詭異座每,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)摘悴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)峭梳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蹂喻,你說(shuō)我怎么就攤上這事葱椭。” “怎么了叉橱?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)者蠕。 經(jīng)常有香客問(wèn)我窃祝,道長(zhǎng),這世上最難降的妖魔是什么踱侣? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任粪小,我火速辦了婚禮大磺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘探膊。我一直安慰自己杠愧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布逞壁。 她就那樣靜靜地躺著流济,像睡著了一般。 火紅的嫁衣襯著肌膚如雪腌闯。 梳的紋絲不亂的頭發(fā)上绳瘟,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音姿骏,去河邊找鬼糖声。 笑死,一個(gè)胖子當(dāng)著我的面吹牛分瘦,可吹牛的內(nèi)容都是我干的蘸泻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嘲玫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼悦施!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起趁冈,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤歼争,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后渗勘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體沐绒,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年旺坠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乔遮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡取刃,死狀恐怖蹋肮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情璧疗,我是刑警寧澤坯辩,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站崩侠,受9級(jí)特大地震影響漆魔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一改抡、第九天 我趴在偏房一處隱蔽的房頂上張望矢炼。 院中可真熱鬧,春花似錦阿纤、人聲如沸句灌。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胰锌。三九已至,卻和暖如春清蚀,著一層夾襖步出監(jiān)牢的瞬間匕荸,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工枷邪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留榛搔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓践惑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親尔觉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354